Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 83269f3

Browse files
[local_auth] Fix default deviceSupportsBiometrics (#5321)
1 parent 1925b91 commit 83269f3

File tree

4 files changed

+46
-7
lines changed

4 files changed

+46
-7
lines changed

packages/local_auth/local_auth_platform_interface/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 1.0.3
2+
3+
* Fixes regression in the default method channel implementation of
4+
`deviceSupportsBiometrics` from federation that would cause it to return true
5+
only if something is enrolled.
6+
17
## 1.0.2
28

39
* Adopts `Object.hash`.

packages/local_auth/local_auth_platform_interface/lib/default_method_channel_platform.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ class DefaultLocalAuthPlatform extends LocalAuthPlatform {
5757
biometrics.add(BiometricType.iris);
5858
break;
5959
case 'undefined':
60+
// Sentinel value for the case when nothing is enrolled, but hardware
61+
// support for biometrics is available.
6062
break;
6163
}
6264
}
@@ -65,7 +67,14 @@ class DefaultLocalAuthPlatform extends LocalAuthPlatform {
6567

6668
@override
6769
Future<bool> deviceSupportsBiometrics() async {
68-
return (await getEnrolledBiometrics()).isNotEmpty;
70+
final List<String> availableBiometrics =
71+
(await _channel.invokeListMethod<String>(
72+
'getAvailableBiometrics',
73+
)) ??
74+
<String>[];
75+
// If anything, including the 'undefined' sentinel, is returned, then there
76+
// is device support for biometrics.
77+
return availableBiometrics.isNotEmpty;
6978
}
7079

7180
@override

packages/local_auth/local_auth_platform_interface/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ repository: https://github.com/flutter/plugins/tree/master/packages/local_auth/l
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+local_auth%22
55
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
66
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
7-
version: 1.0.2
7+
version: 1.0.3
88

99
environment:
1010
sdk: ">=2.14.0 <3.0.0"

packages/local_auth/local_auth_platform_interface/test/default_method_channel_platform_test.dart

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import 'package:local_auth_platform_interface/default_method_channel_platform.da
1010
import 'package:local_auth_platform_interface/local_auth_platform_interface.dart';
1111
import 'package:local_auth_platform_interface/types/auth_messages.dart';
1212
import 'package:local_auth_platform_interface/types/auth_options.dart';
13-
import 'package:local_auth_platform_interface/types/biometric_type.dart';
1413

1514
void main() {
1615
TestWidgetsFlutterBinding.ensureInitialized();
@@ -19,9 +18,13 @@ void main() {
1918
'plugins.flutter.io/local_auth',
2019
);
2120

22-
final List<MethodCall> log = <MethodCall>[];
21+
late List<MethodCall> log;
2322
late LocalAuthPlatform localAuthentication;
2423

24+
setUp(() async {
25+
log = <MethodCall>[];
26+
});
27+
2528
test(
2629
'DefaultLocalAuthPlatform is registered as the default platform implementation',
2730
() async {
@@ -32,10 +35,9 @@ void main() {
3235
test('getAvailableBiometrics', () async {
3336
channel.setMockMethodCallHandler((MethodCall methodCall) {
3437
log.add(methodCall);
35-
return Future<dynamic>.value(<BiometricType>[]);
38+
return Future<dynamic>.value(<String>[]);
3639
});
3740
localAuthentication = DefaultLocalAuthPlatform();
38-
log.clear();
3941
await localAuthentication.getEnrolledBiometrics();
4042
expect(
4143
log,
@@ -45,14 +47,36 @@ void main() {
4547
);
4648
});
4749

50+
test('deviceSupportsBiometrics handles special sentinal value', () async {
51+
// The pre-federation implementation of the platform channels, which the
52+
// default implementation retains compatibility with for the benefit of any
53+
// existing unendorsed implementations, used 'undefined' as a special
54+
// return value from `getAvailableBiometrics` to indicate that nothing was
55+
// enrolled, but that the hardware does support biometrics.
56+
channel.setMockMethodCallHandler((MethodCall methodCall) {
57+
log.add(methodCall);
58+
return Future<dynamic>.value(<String>['undefined']);
59+
});
60+
61+
localAuthentication = DefaultLocalAuthPlatform();
62+
final bool supportsBiometrics =
63+
await localAuthentication.deviceSupportsBiometrics();
64+
expect(supportsBiometrics, true);
65+
expect(
66+
log,
67+
<Matcher>[
68+
isMethodCall('getAvailableBiometrics', arguments: null),
69+
],
70+
);
71+
});
72+
4873
group('Boolean returning methods', () {
4974
setUp(() {
5075
channel.setMockMethodCallHandler((MethodCall methodCall) {
5176
log.add(methodCall);
5277
return Future<dynamic>.value(true);
5378
});
5479
localAuthentication = DefaultLocalAuthPlatform();
55-
log.clear();
5680
});
5781

5882
test('isDeviceSupported', () async {

0 commit comments

Comments
 (0)