Skip to content

Commit 2c0fc55

Browse files
[webview_flutter] Adds support to receive permission requests (flutter#3543)
~~Aggregate implementation of flutter#78147 Fixes flutter#78147 Fixes flutter#56871
1 parent 500c8ad commit 2c0fc55

11 files changed

+168
-20
lines changed

packages/webview_flutter/webview_flutter/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 4.2.0
2+
3+
* Adds support to receive permission requests. See `WebViewController(onPermissionRequest)`.
4+
15
## 4.1.0
26

37
* Adds support to track URL changes. See `NavigationDelegate(onUrlChange)`.

packages/webview_flutter/webview_flutter/example/pubspec.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ dependencies:
1717
# The example app is bundled with the plugin so we use a path dependency on
1818
# the parent directory to use the current plugin's version.
1919
path: ../
20-
webview_flutter_android: ^3.5.0
21-
webview_flutter_wkwebview: ^3.3.0
20+
webview_flutter_android: ^3.6.0
21+
webview_flutter_wkwebview: ^3.4.0
2222

2323
dev_dependencies:
2424
build_runner: ^2.1.5
@@ -29,7 +29,7 @@ dev_dependencies:
2929
sdk: flutter
3030
integration_test:
3131
sdk: flutter
32-
webview_flutter_platform_interface: ^2.1.0
32+
webview_flutter_platform_interface: ^2.3.0
3333

3434
flutter:
3535
uses-material-design: true

packages/webview_flutter/webview_flutter/lib/src/navigation_delegate.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import 'webview_controller.dart';
3737
class NavigationDelegate {
3838
/// Constructs a [NavigationDelegate].
3939
///
40-
/// {@template webview_fluttter.navigation_delegate.constructor}
40+
/// {@template webview_fluttter.NavigationDelegate.constructor}
4141
/// `onUrlChange`: invoked when the underlying web view changes to a new url.
4242
/// {@endtemplate}
4343
NavigationDelegate({
@@ -61,6 +61,8 @@ class NavigationDelegate {
6161
/// Constructs a [NavigationDelegate] from creation params for a specific
6262
/// platform.
6363
///
64+
/// {@macro webview_fluttter.NavigationDelegate.constructor}
65+
///
6466
/// {@template webview_flutter.NavigationDelegate.fromPlatformCreationParams}
6567
/// Below is an example of setting platform-specific creation parameters for
6668
/// iOS and Android:
@@ -87,8 +89,6 @@ class NavigationDelegate {
8789
/// );
8890
/// ```
8991
/// {@endtemplate}
90-
///
91-
/// {@macro webview_fluttter.navigation_delegate.constructor}
9292
NavigationDelegate.fromPlatformCreationParams(
9393
PlatformNavigationDelegateCreationParams params, {
9494
FutureOr<NavigationDecision> Function(NavigationRequest request)?
@@ -110,7 +110,7 @@ class NavigationDelegate {
110110

111111
/// Constructs a [NavigationDelegate] from a specific platform implementation.
112112
///
113-
/// {@macro webview_fluttter.navigation_delegate.constructor}
113+
/// {@macro webview_fluttter.NavigationDelegate.constructor}
114114
NavigationDelegate.fromPlatform(
115115
this.platform, {
116116
this.onNavigationRequest,

packages/webview_flutter/webview_flutter/lib/src/webview_controller.dart

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,33 @@ import 'webview_widget.dart';
4343
class WebViewController {
4444
/// Constructs a [WebViewController].
4545
///
46+
/// {@template webview_fluttter.WebViewController.constructor}
47+
/// `onPermissionRequest`: A callback that notifies the host application that
48+
/// web content is requesting permission to access the specified resources.
49+
/// To grant access for a device resource, most platforms will need to update
50+
/// their app configurations for the relevant system resource.
51+
///
52+
/// For Android, you will need to update your `AndroidManifest.xml`. See
53+
/// https://developer.android.com/training/permissions/declaring
54+
///
55+
/// For iOS, you will need to update your `Info.plist`. See
56+
/// https://developer.apple.com/documentation/uikit/protecting_the_user_s_privacy/requesting_access_to_protected_resources?language=objc.
57+
/// {@endtemplate}
58+
///
4659
/// See [WebViewController.fromPlatformCreationParams] for setting parameters
4760
/// for a specific platform.
48-
WebViewController()
49-
: this.fromPlatformCreationParams(
61+
WebViewController({
62+
void Function(WebViewPermissionRequest request)? onPermissionRequest,
63+
}) : this.fromPlatformCreationParams(
5064
const PlatformWebViewControllerCreationParams(),
65+
onPermissionRequest: onPermissionRequest,
5166
);
5267

5368
/// Constructs a [WebViewController] from creation params for a specific
5469
/// platform.
5570
///
71+
/// {@macro webview_fluttter.WebViewController.constructor}
72+
///
5673
/// {@template webview_flutter.WebViewController.fromPlatformCreationParams}
5774
/// Below is an example of setting platform-specific creation parameters for
5875
/// iOS and Android:
@@ -80,11 +97,31 @@ class WebViewController {
8097
/// ```
8198
/// {@endtemplate}
8299
WebViewController.fromPlatformCreationParams(
83-
PlatformWebViewControllerCreationParams params,
84-
) : this.fromPlatform(PlatformWebViewController(params));
100+
PlatformWebViewControllerCreationParams params, {
101+
void Function(WebViewPermissionRequest request)? onPermissionRequest,
102+
}) : this.fromPlatform(
103+
PlatformWebViewController(params),
104+
onPermissionRequest: onPermissionRequest,
105+
);
85106

86107
/// Constructs a [WebViewController] from a specific platform implementation.
87-
WebViewController.fromPlatform(this.platform);
108+
///
109+
/// {@macro webview_fluttter.WebViewController.constructor}
110+
WebViewController.fromPlatform(
111+
this.platform, {
112+
void Function(WebViewPermissionRequest request)? onPermissionRequest,
113+
}) {
114+
if (onPermissionRequest != null) {
115+
platform.setOnPlatformPermissionRequest(
116+
(PlatformWebViewPermissionRequest request) {
117+
onPermissionRequest(WebViewPermissionRequest._(
118+
request,
119+
types: request.types,
120+
));
121+
},
122+
);
123+
}
124+
}
88125

89126
/// Implementation of [PlatformWebViewController] for the current platform.
90127
final PlatformWebViewController platform;
@@ -319,3 +356,49 @@ class WebViewController {
319356
return platform.setUserAgent(userAgent);
320357
}
321358
}
359+
360+
/// Permissions request when web content requests access to protected resources.
361+
///
362+
/// A response MUST be provided by calling [grant], [deny], or a method from
363+
/// [platform].
364+
///
365+
/// ## Platform-Specific Features
366+
/// This class contains an underlying implementation provided by the current
367+
/// platform. Once a platform implementation is imported, the example below
368+
/// can be followed to use features provided by a platform's implementation.
369+
///
370+
/// Below is an example of accessing the platform-specific implementation for
371+
/// iOS and Android:
372+
///
373+
/// ```dart
374+
/// final WebViewPermissionRequest request = ...;
375+
///
376+
/// if (WebViewPlatform.instance is WebKitWebViewPlatform) {
377+
/// final WebKitWebViewPermissionRequest webKitRequest =
378+
/// request.platform as WebKitWebViewPermissionRequest;
379+
/// } else if (WebViewPlatform.instance is AndroidWebViewPlatform) {
380+
/// final AndroidWebViewPermissionRequest androidRequest =
381+
/// request.platform as AndroidWebViewPermissionRequest;
382+
/// }
383+
/// ```
384+
@immutable
385+
class WebViewPermissionRequest {
386+
const WebViewPermissionRequest._(this.platform, {required this.types});
387+
388+
/// All resources access has been requested for.
389+
final Set<WebViewPermissionResourceType> types;
390+
391+
/// Implementation of [PlatformWebViewPermissionRequest] for the current
392+
/// platform.
393+
final PlatformWebViewPermissionRequest platform;
394+
395+
/// Grant permission for the requested resource(s).
396+
Future<void> grant() {
397+
return platform.grant();
398+
}
399+
400+
/// Deny permission for the requested resource(s).
401+
Future<void> deny() {
402+
return platform.deny();
403+
}
404+
}

packages/webview_flutter/webview_flutter/lib/webview_flutter.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ export 'package:webview_flutter_platform_interface/webview_flutter_platform_inte
1616
PlatformNavigationDelegateCreationParams,
1717
PlatformWebViewControllerCreationParams,
1818
PlatformWebViewCookieManagerCreationParams,
19+
PlatformWebViewPermissionRequest,
1920
PlatformWebViewWidgetCreationParams,
2021
ProgressCallback,
2122
UrlChange,
2223
WebResourceError,
2324
WebResourceErrorCallback,
2425
WebResourceErrorType,
2526
WebViewCookie,
27+
WebViewPermissionResourceType,
2628
WebViewPlatform;
2729

2830
export 'src/navigation_delegate.dart';

packages/webview_flutter/webview_flutter/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: webview_flutter
22
description: A Flutter plugin that provides a WebView widget on Android and iOS.
33
repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
5-
version: 4.1.0
5+
version: 4.2.0
66

77
environment:
88
sdk: ">=2.18.0 <4.0.0"
@@ -20,7 +20,7 @@ dependencies:
2020
flutter:
2121
sdk: flutter
2222
webview_flutter_android: ^3.0.0
23-
webview_flutter_platform_interface: ^2.1.0
23+
webview_flutter_platform_interface: ^2.3.0
2424
webview_flutter_wkwebview: ^3.0.0
2525

2626
dev_dependencies:

packages/webview_flutter/webview_flutter/test/webview_controller_test.dart

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,4 +365,38 @@ void main() {
365365
mockPlatformNavigationDelegate,
366366
));
367367
});
368+
369+
test('onPermissionRequest', () async {
370+
bool permissionRequestCallbackCalled = false;
371+
372+
final MockPlatformWebViewController mockPlatformWebViewController =
373+
MockPlatformWebViewController();
374+
WebViewController.fromPlatform(
375+
mockPlatformWebViewController,
376+
onPermissionRequest: (WebViewPermissionRequest request) {
377+
permissionRequestCallbackCalled = true;
378+
},
379+
);
380+
381+
final void Function(PlatformWebViewPermissionRequest request)
382+
requestCallback = verify(mockPlatformWebViewController
383+
.setOnPlatformPermissionRequest(captureAny))
384+
.captured
385+
.single as void Function(PlatformWebViewPermissionRequest request);
386+
387+
requestCallback(const TestPlatformWebViewPermissionRequest());
388+
expect(permissionRequestCallbackCalled, isTrue);
389+
});
390+
}
391+
392+
class TestPlatformWebViewPermissionRequest
393+
extends PlatformWebViewPermissionRequest {
394+
const TestPlatformWebViewPermissionRequest()
395+
: super(types: const <WebViewPermissionResourceType>{});
396+
397+
@override
398+
Future<void> grant() async {}
399+
400+
@override
401+
Future<void> deny() async {}
368402
}

packages/webview_flutter/webview_flutter/test/webview_controller_test.mocks.dart

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import 'package:webview_flutter_platform_interface/src/platform_navigation_deleg
1111
as _i6;
1212
import 'package:webview_flutter_platform_interface/src/platform_webview_controller.dart'
1313
as _i4;
14-
import 'package:webview_flutter_platform_interface/src/webview_platform.dart'
15-
as _i2;
14+
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i2;
1615

1716
// ignore_for_file: type=lint
1817
// ignore_for_file: avoid_redundant_argument_values
@@ -342,6 +341,18 @@ class MockPlatformWebViewController extends _i1.Mock
342341
returnValue: _i5.Future<void>.value(),
343342
returnValueForMissingStub: _i5.Future<void>.value(),
344343
) as _i5.Future<void>);
344+
@override
345+
_i5.Future<void> setOnPlatformPermissionRequest(
346+
void Function(_i2.PlatformWebViewPermissionRequest)?
347+
onPermissionRequest) =>
348+
(super.noSuchMethod(
349+
Invocation.method(
350+
#setOnPlatformPermissionRequest,
351+
[onPermissionRequest],
352+
),
353+
returnValue: _i5.Future<void>.value(),
354+
returnValueForMissingStub: _i5.Future<void>.value(),
355+
) as _i5.Future<void>);
345356
}
346357

347358
/// A class which mocks [PlatformNavigationDelegate].

packages/webview_flutter/webview_flutter/test/webview_cookie_manager_test.mocks.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import 'dart:async' as _i4;
88
import 'package:mockito/mockito.dart' as _i1;
99
import 'package:webview_flutter_platform_interface/src/platform_webview_cookie_manager.dart'
1010
as _i3;
11-
import 'package:webview_flutter_platform_interface/src/webview_platform.dart'
12-
as _i2;
11+
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i2;
1312

1413
// ignore_for_file: type=lint
1514
// ignore_for_file: avoid_redundant_argument_values

packages/webview_flutter/webview_flutter/test/webview_flutter_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ void main() {
3030
// ignore: unnecessary_statements
3131
main_file.PlatformWebViewCookieManagerCreationParams;
3232
// ignore: unnecessary_statements
33+
main_file.PlatformWebViewPermissionRequest;
34+
// ignore: unnecessary_statements
3335
main_file.PlatformWebViewWidgetCreationParams;
3436
// ignore: unnecessary_statements
3537
main_file.ProgressCallback;
3638
// ignore: unnecessary_statements
39+
main_file.WebViewPermissionResourceType;
40+
// ignore: unnecessary_statements
3741
main_file.WebResourceError;
3842
// ignore: unnecessary_statements
3943
main_file.WebResourceErrorCallback;

packages/webview_flutter/webview_flutter/test/webview_widget_test.mocks.dart

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ import 'package:webview_flutter_platform_interface/src/platform_webview_controll
1515
as _i6;
1616
import 'package:webview_flutter_platform_interface/src/platform_webview_widget.dart'
1717
as _i9;
18-
import 'package:webview_flutter_platform_interface/src/webview_platform.dart'
19-
as _i2;
18+
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i2;
2019

2120
// ignore_for_file: type=lint
2221
// ignore_for_file: avoid_redundant_argument_values
@@ -360,6 +359,18 @@ class MockPlatformWebViewController extends _i1.Mock
360359
returnValue: _i7.Future<void>.value(),
361360
returnValueForMissingStub: _i7.Future<void>.value(),
362361
) as _i7.Future<void>);
362+
@override
363+
_i7.Future<void> setOnPlatformPermissionRequest(
364+
void Function(_i2.PlatformWebViewPermissionRequest)?
365+
onPermissionRequest) =>
366+
(super.noSuchMethod(
367+
Invocation.method(
368+
#setOnPlatformPermissionRequest,
369+
[onPermissionRequest],
370+
),
371+
returnValue: _i7.Future<void>.value(),
372+
returnValueForMissingStub: _i7.Future<void>.value(),
373+
) as _i7.Future<void>);
363374
}
364375

365376
/// A class which mocks [PlatformWebViewWidget].

0 commit comments

Comments
 (0)