Commit 9907d20b by Eugene Kuleshov Committed by GitHub

Html non secure permissions (#1240)

* fixed plugin init with non-https web app

* fixed plugin init with non-https web app

* fixed handling of nullable values

* fixed _locationPermissionName

* better error handling

* PR feedback

* PR feedback
parent e3c92e38
## 0.1.1
* Fixed plugin initialization for non-https web app.
* Fixed location permission name
* Improved error handling in the example app
## 0.1.0+1
* Updates `permission_handler_platform_interface` dependency to version `^4.0.2`.
......
......@@ -11,21 +11,17 @@ void main() {
}
///Defines the main theme color
final MaterialColor themeMaterialColor =
BaseflowPluginExample.createMaterialColor(
const Color.fromRGBO(48, 49, 60, 1));
final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor(const Color.fromRGBO(48, 49, 60, 1));
/// A Flutter application demonstrating the functionality of this plugin
class PermissionHandlerWidget extends StatefulWidget {
/// Create a page containing the functionality of this plugin
static ExamplePage createPage() {
return ExamplePage(
Icons.location_on, (context) => PermissionHandlerWidget());
return ExamplePage(Icons.location_on, (context) => PermissionHandlerWidget());
}
@override
_PermissionHandlerWidgetState createState() =>
_PermissionHandlerWidgetState();
_PermissionHandlerWidgetState createState() => _PermissionHandlerWidgetState();
}
class _PermissionHandlerWidgetState extends State<PermissionHandlerWidget> {
......@@ -64,8 +60,7 @@ class _PermissionState extends State<PermissionWidget> {
_PermissionState(this._permission);
final Permission _permission;
final PermissionHandlerPlatform _permissionHandler =
PermissionHandlerPlatform.instance;
final PermissionHandlerPlatform _permissionHandler = PermissionHandlerPlatform.instance;
PermissionStatus _permissionStatus = PermissionStatus.denied;
@override
......@@ -76,8 +71,9 @@ class _PermissionState extends State<PermissionWidget> {
}
void _listenForPermissionStatus() async {
final status = await _permissionHandler.checkPermissionStatus(_permission);
setState(() => _permissionStatus = status);
await _permissionHandler
.checkPermissionStatus(_permission)
.then((status) => setState(() => _permissionStatus = status), onError: (error, st) => print('$error'));
}
Color getPermissionColor() {
......@@ -111,8 +107,7 @@ class _PermissionState extends State<PermissionWidget> {
color: Colors.white,
),
onPressed: () {
checkServiceStatus(
context, _permission as PermissionWithService);
checkServiceStatus(context, _permission as PermissionWithService);
})
: null,
onTap: () {
......@@ -121,21 +116,19 @@ class _PermissionState extends State<PermissionWidget> {
);
}
void checkServiceStatus(
BuildContext context, PermissionWithService permission) async {
void checkServiceStatus(BuildContext context, PermissionWithService permission) async {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
(await _permissionHandler.checkServiceStatus(permission)).toString()),
content: Text((await _permissionHandler.checkServiceStatus(permission)).toString()),
));
}
Future<void> requestPermission(Permission permission) async {
final status = await _permissionHandler.requestPermissions([permission]);
setState(() {
await _permissionHandler.requestPermissions([permission]).then(
(status) => setState(() {
print(status);
_permissionStatus = status[permission] ?? PermissionStatus.denied;
print(_permissionStatus);
});
}),
onError: (error, st) => print('$error'));
}
}
......@@ -9,7 +9,7 @@ import 'web_delegate.dart';
/// Platform implementation of the permission_handler Flutter plugin.
class WebPermissionHandler extends PermissionHandlerPlatform {
static final html.MediaDevices _devices = html.window.navigator.mediaDevices!;
static final html.MediaDevices? _devices = html.window.navigator.mediaDevices;
static final html.Geolocation _geolocation =
html.window.navigator.geolocation;
static final html.Permissions? _htmlPermissions =
......
......@@ -34,7 +34,8 @@ class WebDelegate {
static const _notificationsPermissionName = 'notifications';
/// The permission name to request access to the user's location.
static const _locationPermissionName = 'location';
/// https://developer.mozilla.org/en-US/docs/Web/API/Permissions/query#name
static const _locationPermissionName = 'geolocation';
/// The status indicates that permission has been granted by the user.
static const _grantedPermissionStatus = 'granted';
......@@ -57,18 +58,18 @@ class WebDelegate {
}
}
Future<PermissionStatus> _permissionStatusState(
String webPermissionName, html.Permissions? permissions) async {
final webPermissionStatus =
await permissions?.query({'name': webPermissionName});
Future<PermissionStatus> _permissionStatusState(String webPermissionName, html.Permissions? permissions) async {
final webPermissionStatus = await permissions?.query({'name': webPermissionName});
return _toPermissionStatus(webPermissionStatus?.state);
}
Future<bool> _requestMicrophonePermission(html.MediaDevices devices) async {
html.MediaStream? mediaStream;
Future<bool> _requestMicrophonePermission() async {
if (_devices == null) {
return false;
}
try {
mediaStream = await devices.getUserMedia({'audio': true});
html.MediaStream mediaStream = await _devices!.getUserMedia({'audio': true});
// In browsers, calling [getUserMedia] will start the recording
// automatically right after. This is undesired behavior as
......@@ -77,7 +78,7 @@ class WebDelegate {
// The manual stop action is then needed here for to stop the automatic
// recording.
if (mediaStream.active!) {
if (mediaStream.active ?? false) {
final audioTracks = mediaStream.getAudioTracks();
if (audioTracks.isNotEmpty) {
audioTracks[0].stop();
......@@ -90,11 +91,13 @@ class WebDelegate {
return true;
}
Future<bool> _requestCameraPermission(html.MediaDevices devices) async {
html.MediaStream? mediaStream;
Future<bool> _requestCameraPermission() async {
if (_devices == null) {
return false;
}
try {
mediaStream = await devices.getUserMedia({'video': true});
html.MediaStream mediaStream = await _devices!.getUserMedia({'video': true});
// In browsers, calling [getUserMedia] will start the recording
// automatically right after. This is undesired behavior as
......@@ -103,7 +106,7 @@ class WebDelegate {
// The manual stop action is then needed here for to stop the automatic
// recording.
if (mediaStream.active!) {
if (mediaStream.active ?? false) {
final videoTracks = mediaStream.getVideoTracks();
if (videoTracks.isNotEmpty) {
videoTracks[0].stop();
......@@ -117,45 +120,25 @@ class WebDelegate {
}
Future<bool> _requestNotificationPermission() async {
bool granted = false;
html.Notification.requestPermission().then((permission) => {
if (permission == "granted") {granted = true}
});
return granted;
return html.Notification.requestPermission().then((permission) => permission == "granted");
}
Future<bool> _requestLocationPermission(html.Geolocation geolocation) async {
Future<bool> _requestLocationPermission() async {
try {
await geolocation.getCurrentPosition();
return true;
return await _geolocation?.getCurrentPosition().then((value) => true) ?? false;
} on html.PositionError {
return false;
}
}
Future<PermissionStatus> _requestSingularPermission(
Permission permission) async {
bool permissionGranted = false;
switch (permission) {
case Permission.microphone:
permissionGranted = await _requestMicrophonePermission(_devices!);
break;
case Permission.camera:
permissionGranted = await _requestCameraPermission(_devices!);
break;
case Permission.notification:
permissionGranted = await _requestNotificationPermission();
break;
case Permission.location:
permissionGranted = await _requestLocationPermission(_geolocation!);
break;
default:
throw UnsupportedError(
'The ${permission.toString()} permission is currently not supported on web.',
);
}
Future<PermissionStatus> _requestSingularPermission(Permission permission) async {
bool permissionGranted = switch (permission) {
Permission.microphone => await _requestMicrophonePermission(),
Permission.camera => await _requestCameraPermission(),
Permission.notification => await _requestNotificationPermission(),
Permission.location => await _requestLocationPermission(),
_ => throw UnsupportedError('The ${permission.toString()} permission is currently not supported on web.')
};
if (!permissionGranted) {
return PermissionStatus.permanentlyDenied;
......@@ -167,14 +150,12 @@ class WebDelegate {
/// they have not already been granted before.
///
/// Returns a [Map] containing the status per requested [Permission].
Future<Map<Permission, PermissionStatus>> requestPermissions(
List<Permission> permissions) async {
Future<Map<Permission, PermissionStatus>> requestPermissions(List<Permission> permissions) async {
final Map<Permission, PermissionStatus> permissionStatusMap = {};
for (final permission in permissions) {
try {
permissionStatusMap[permission] =
await _requestSingularPermission(permission);
permissionStatusMap[permission] = await _requestSingularPermission(permission);
} on UnimplementedError {
rethrow;
}
......
name: permission_handler_html
description: Permission plugin for Flutter. This plugin provides the web API to request and check permissions.
version: 0.1.0+1
version: 0.1.1
homepage: https://github.com/baseflow/flutter-permission-handler
environment:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment