Skip to content

Commit 773b298

Browse files
committed
code review fixes
1 parent 7f54679 commit 773b298

7 files changed

Lines changed: 232 additions & 17 deletions

File tree

packages/webview_flutter/webview_flutter_android/README.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,29 @@ Add intent filters to your AndroidManifest.xml to discover and invoke Android pa
8585

8686
## Enable Web Authentication in WebView
8787

88-
Web Authentication can be enabled by calling `AndroidWebViewController.setWebAuthenticationEnabled` after
89-
checking `AndroidWebViewController.isWebViewFeatureSupported`.
88+
WebAuthentication (WebAuthn) can be configured by calling
89+
`AndroidWebViewController.setWebAuthenticationSupport` after checking
90+
`AndroidWebViewController.isWebViewFeatureSupported`.
91+
92+
The WebAuthentication support level can be set to one of three values:
93+
- **[WebAuthenticationSupport.none]**: Disables all WebAuthn requests
94+
- **[WebAuthenticationSupport.forApp]**: Allows WebAuthn for the embedded application (default)
95+
- **[WebAuthenticationSupport.forBrowser]**: Allows WebAuthn for any website (browser-like behavior)
9096

9197
<?code-excerpt "example/lib/readme_excerpts.dart (web_authentication_example)"?>
9298
```dart
93-
final bool webAuthenticationEnabled = await androidController
99+
final bool webAuthenticationSupported = await androidController
94100
.isWebViewFeatureSupported(WebViewFeatureType.webAuthentication);
95101
96-
if (webAuthenticationEnabled) {
97-
await androidController.setWebAuthenticationEnabled(true);
102+
if (webAuthenticationSupported) {
103+
// Enable WebAuthn for the embedded app
104+
await androidController.setWebAuthenticationSupport(
105+
WebAuthenticationSupport.forApp,
106+
);
107+
// Or for browser-like behavior supporting any website:
108+
// await androidController.setWebAuthenticationSupport(
109+
// WebAuthenticationSupport.forBrowser,
110+
// );
98111
}
99112
```
100113

packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebSettingsCompatProxyApi.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ public void setPaymentRequestEnabled(@NonNull WebSettings webSettings, boolean e
3333
/**
3434
* This method should only be called if {@link WebViewFeatureProxyApi#isFeatureSupported(String)}
3535
* with WEB_AUTHENTICATION returns true.
36+
*
37+
* <p>The {@code support} parameter is a {@code long} to accommodate Dart's integer type, but is
38+
* safely converted to {@code int} for the underlying Android API call. {@link
39+
* Math#toIntExact(long)} is used to verify the value fits in the {@code int} range and throw
40+
* {@link ArithmeticException} if it overflows. This is safe because the valid support levels are
41+
* constants (0, 1, 2) that well within the integer range.
42+
*
43+
* <p>Note: {@link Math#toIntExact(long)} requires API level 24 or higher. This is compatible with
44+
* this plugin's minimum SDK version.
45+
*
46+
* @param webSettings the WebSettings instance
47+
* @param support the WebAuthentication support level (0, 1, or 2)
48+
* @throws ArithmeticException if {@code support} exceeds {@link Integer#MAX_VALUE}
3649
*/
3750
@SuppressLint("RequiresFeature")
3851
@Override

packages/webview_flutter/webview_flutter_android/example/lib/readme_excerpts.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,18 @@ Future<void> enableWebAuthentication() async {
2828
);
2929
final androidController = controller as AndroidWebViewController;
3030
// #docregion web_authentication_example
31-
final bool webAuthenticationEnabled = await androidController
31+
final bool webAuthenticationSupported = await androidController
3232
.isWebViewFeatureSupported(WebViewFeatureType.webAuthentication);
3333

34-
if (webAuthenticationEnabled) {
35-
await androidController.setWebAuthenticationEnabled(true);
34+
if (webAuthenticationSupported) {
35+
// Enable WebAuthn for the embedded app
36+
await androidController.setWebAuthenticationSupport(
37+
WebAuthenticationSupport.forApp,
38+
);
39+
// Or for browser-like behavior supporting any website:
40+
// await androidController.setWebAuthenticationSupport(
41+
// WebAuthenticationSupport.forBrowser,
42+
// );
3643
}
3744
// #enddocregion web_authentication_example
3845
}

packages/webview_flutter/webview_flutter_android/lib/src/android_webkit_constants.dart

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,33 @@ class WebViewFeatureConstants {
135135
}
136136

137137
/// Support levels for [WebSettingsCompat.setWebAuthenticationSupport].
138+
///
139+
/// This enum provides a type-safe way to specify the WebAuthentication support
140+
/// level for a WebView.
141+
///
142+
/// See https://developer.android.com/reference/androidx/webkit/WebSettingsCompat#setWebAuthenticationSupport.
143+
enum WebAuthenticationSupport {
144+
/// Disables WebAuthn requests from WebView.
145+
///
146+
/// No WebAuthn APIs are available to web content in the WebView.
147+
none,
148+
149+
/// Allows WebAuthn requests for the embedded app.
150+
///
151+
/// WebAuthn is available for Relying Party IDs that are registered for the
152+
/// embedding application.
153+
forApp,
154+
155+
/// Allows WebAuthn calls for any website.
156+
///
157+
/// WebAuthn is available for any Relying Party ID. This is the typical
158+
/// configuration for a browser-like experience.
159+
forBrowser,
160+
}
161+
162+
/// Support levels for [WebSettingsCompat.setWebAuthenticationSupport].
163+
///
164+
/// @deprecated Use [WebAuthenticationSupport] enum instead for type-safe support level selection.
138165
class WebAuthenticationSupportConstants {
139166
/// Disables WebAuthn requests from WebView.
140167
static const int none = 0;

packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -889,27 +889,71 @@ class AndroidWebViewController extends PlatformWebViewController {
889889
return android_webview.WebViewFeature.isFeatureSupported(feature);
890890
}
891891

892-
/// Enables WebAuthn support for this WebView when available.
892+
/// Sets the WebAuthentication support level for this WebView when available.
893+
///
894+
/// This method configures which contexts can use WebAuthn APIs in the WebView.
895+
/// The WebView must support the feature (check with [isWebViewFeatureSupported]
896+
/// before calling).
897+
///
898+
/// **Parameters:**
899+
/// * [support] - The desired WebAuthentication support level:
900+
/// - [WebAuthenticationSupport.none]: Disables all WebAuthn requests
901+
/// - [WebAuthenticationSupport.forApp]: Allows WebAuthn for the embedded app
902+
/// - [WebAuthenticationSupport.forBrowser]: Allows WebAuthn for any website
903+
///
904+
/// **Example:**
905+
/// ```dart
906+
/// final isSupported = await controller
907+
/// .isWebViewFeatureSupported(WebViewFeatureType.webAuthentication);
908+
/// if (isSupported) {
909+
/// await controller.setWebAuthenticationSupport(
910+
/// WebAuthenticationSupport.forApp,
911+
/// );
912+
/// }
913+
/// ```
893914
///
894-
/// When enabled, this configures the WebView to allow WebAuthn requests for
895-
/// the embedded app.
896-
Future<void> setWebAuthenticationEnabled(bool enabled) async {
915+
/// See https://developer.android.com/reference/androidx/webkit/WebSettingsCompat#setWebAuthenticationSupport.
916+
Future<void> setWebAuthenticationSupport(
917+
WebAuthenticationSupport support,
918+
) async {
897919
if (!await isWebViewFeatureSupported(
898920
WebViewFeatureType.webAuthentication,
899921
)) {
900922
return;
901923
}
902924

903-
final int supportLevel = enabled
904-
? WebAuthenticationSupportConstants.forApp
905-
: WebAuthenticationSupportConstants.none;
906-
925+
final int supportValue = _webAuthenticationSupportToInt(support);
907926
await android_webview.WebSettingsCompat.setWebAuthenticationSupport(
908927
_webView.settings,
909-
supportLevel,
928+
supportValue,
910929
);
911930
}
912931

932+
/// Enables WebAuthn support for this WebView when available.
933+
///
934+
/// This is a convenience method that maps boolean values to [WebAuthenticationSupport]
935+
/// levels:
936+
/// - `true`[WebAuthenticationSupport.forApp]
937+
/// - `false`[WebAuthenticationSupport.none]
938+
///
939+
/// @deprecated Use [setWebAuthenticationSupport] instead for explicit control
940+
/// over all WebAuthentication support levels (none, forApp, forBrowser).
941+
Future<void> setWebAuthenticationEnabled(bool enabled) {
942+
return setWebAuthenticationSupport(
943+
enabled ? WebAuthenticationSupport.forApp : WebAuthenticationSupport.none,
944+
);
945+
}
946+
947+
static int _webAuthenticationSupportToInt(WebAuthenticationSupport support) {
948+
return switch (support) {
949+
WebAuthenticationSupport.none => WebAuthenticationSupportConstants.none,
950+
WebAuthenticationSupport.forApp =>
951+
WebAuthenticationSupportConstants.forApp,
952+
WebAuthenticationSupport.forBrowser =>
953+
WebAuthenticationSupportConstants.forBrowser,
954+
};
955+
}
956+
913957
/// Sets whether the WebView should enable the Payment Request API.
914958
///
915959
/// This method uses [android_webview.WebSettingsCompat.setPaymentRequestEnabled]

packages/webview_flutter/webview_flutter_android/lib/webview_flutter_android.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
export 'src/android_ssl_auth_error.dart';
6+
export 'src/android_webkit_constants.dart';
67
export 'src/android_webview_controller.dart';
78
export 'src/android_webview_cookie_manager.dart';
89
export 'src/android_webview_platform.dart';

packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,6 +2169,116 @@ void main() {
21692169
expect(capturedSupport, isNull);
21702170
});
21712171

2172+
test('setWebAuthenticationSupport with forApp', () async {
2173+
android_webview.WebSettings? capturedSettings;
2174+
int? capturedSupport;
2175+
2176+
final mockWebView = MockWebView();
2177+
final mockSettings = MockWebSettings();
2178+
final AndroidWebViewController controller = createControllerWithMocks(
2179+
mockWebView: mockWebView,
2180+
mockSettings: mockSettings,
2181+
isWebViewFeatureSupported: (String feature) async {
2182+
expect(WebViewFeatureConstants.webAuthentication, feature);
2183+
return true;
2184+
},
2185+
setWebAuthenticationSupport:
2186+
(android_webview.WebSettings settings, int support) async {
2187+
capturedSettings = settings;
2188+
capturedSupport = support;
2189+
},
2190+
);
2191+
2192+
await controller.setWebAuthenticationSupport(
2193+
WebAuthenticationSupport.forApp,
2194+
);
2195+
2196+
expect(mockSettings, capturedSettings);
2197+
expect(WebAuthenticationSupportConstants.forApp, capturedSupport);
2198+
});
2199+
2200+
test('setWebAuthenticationSupport with forBrowser', () async {
2201+
android_webview.WebSettings? capturedSettings;
2202+
int? capturedSupport;
2203+
2204+
final mockWebView = MockWebView();
2205+
final mockSettings = MockWebSettings();
2206+
final AndroidWebViewController controller = createControllerWithMocks(
2207+
mockWebView: mockWebView,
2208+
mockSettings: mockSettings,
2209+
isWebViewFeatureSupported: (String feature) async {
2210+
expect(WebViewFeatureConstants.webAuthentication, feature);
2211+
return true;
2212+
},
2213+
setWebAuthenticationSupport:
2214+
(android_webview.WebSettings settings, int support) async {
2215+
capturedSettings = settings;
2216+
capturedSupport = support;
2217+
},
2218+
);
2219+
2220+
await controller.setWebAuthenticationSupport(
2221+
WebAuthenticationSupport.forBrowser,
2222+
);
2223+
2224+
expect(mockSettings, capturedSettings);
2225+
expect(WebAuthenticationSupportConstants.forBrowser, capturedSupport);
2226+
});
2227+
2228+
test('setWebAuthenticationSupport with none', () async {
2229+
android_webview.WebSettings? capturedSettings;
2230+
int? capturedSupport;
2231+
2232+
final mockWebView = MockWebView();
2233+
final mockSettings = MockWebSettings();
2234+
final AndroidWebViewController controller = createControllerWithMocks(
2235+
mockWebView: mockWebView,
2236+
mockSettings: mockSettings,
2237+
isWebViewFeatureSupported: (String feature) async {
2238+
expect(WebViewFeatureConstants.webAuthentication, feature);
2239+
return true;
2240+
},
2241+
setWebAuthenticationSupport:
2242+
(android_webview.WebSettings settings, int support) async {
2243+
capturedSettings = settings;
2244+
capturedSupport = support;
2245+
},
2246+
);
2247+
2248+
await controller.setWebAuthenticationSupport(WebAuthenticationSupport.none);
2249+
2250+
expect(mockSettings, capturedSettings);
2251+
expect(WebAuthenticationSupportConstants.none, capturedSupport);
2252+
});
2253+
2254+
test('setWebAuthenticationSupport skips when unsupported', () async {
2255+
android_webview.WebSettings? capturedSettings;
2256+
int? capturedSupport;
2257+
2258+
final mockWebView = MockWebView();
2259+
final mockSettings = MockWebSettings();
2260+
final AndroidWebViewController controller = createControllerWithMocks(
2261+
mockWebView: mockWebView,
2262+
mockSettings: mockSettings,
2263+
isWebViewFeatureSupported: (String feature) async {
2264+
expect(WebViewFeatureConstants.webAuthentication, feature);
2265+
return false;
2266+
},
2267+
setWebAuthenticationSupport:
2268+
(android_webview.WebSettings settings, int support) async {
2269+
capturedSettings = settings;
2270+
capturedSupport = support;
2271+
},
2272+
);
2273+
2274+
await controller.setWebAuthenticationSupport(
2275+
WebAuthenticationSupport.forApp,
2276+
);
2277+
2278+
expect(capturedSettings, isNull);
2279+
expect(capturedSupport, isNull);
2280+
});
2281+
21722282
test('setInsetsForWebContentToIgnore', () async {
21732283
final mockWebView = MockWebView();
21742284
final AndroidWebViewController controller = createControllerWithMocks(

0 commit comments

Comments
 (0)