Skip to content

Commit

Permalink
[webview_flutter] Adds support to receive permission requests (flutte…
Browse files Browse the repository at this point in the history
…r#3543)

~~Aggregate implementation of flutter#78147

Fixes flutter#78147
Fixes flutter#56871
  • Loading branch information
bparrishMines authored Apr 22, 2023
1 parent 500c8ad commit 2c0fc55
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 20 deletions.
4 changes: 4 additions & 0 deletions packages/webview_flutter/webview_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 4.2.0

* Adds support to receive permission requests. See `WebViewController(onPermissionRequest)`.

## 4.1.0

* Adds support to track URL changes. See `NavigationDelegate(onUrlChange)`.
Expand Down
6 changes: 3 additions & 3 deletions packages/webview_flutter/webview_flutter/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ dependencies:
# The example app is bundled with the plugin so we use a path dependency on
# the parent directory to use the current plugin's version.
path: ../
webview_flutter_android: ^3.5.0
webview_flutter_wkwebview: ^3.3.0
webview_flutter_android: ^3.6.0
webview_flutter_wkwebview: ^3.4.0

dev_dependencies:
build_runner: ^2.1.5
Expand All @@ -29,7 +29,7 @@ dev_dependencies:
sdk: flutter
integration_test:
sdk: flutter
webview_flutter_platform_interface: ^2.1.0
webview_flutter_platform_interface: ^2.3.0

flutter:
uses-material-design: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import 'webview_controller.dart';
class NavigationDelegate {
/// Constructs a [NavigationDelegate].
///
/// {@template webview_fluttter.navigation_delegate.constructor}
/// {@template webview_fluttter.NavigationDelegate.constructor}
/// `onUrlChange`: invoked when the underlying web view changes to a new url.
/// {@endtemplate}
NavigationDelegate({
Expand All @@ -61,6 +61,8 @@ class NavigationDelegate {
/// Constructs a [NavigationDelegate] from creation params for a specific
/// platform.
///
/// {@macro webview_fluttter.NavigationDelegate.constructor}
///
/// {@template webview_flutter.NavigationDelegate.fromPlatformCreationParams}
/// Below is an example of setting platform-specific creation parameters for
/// iOS and Android:
Expand All @@ -87,8 +89,6 @@ class NavigationDelegate {
/// );
/// ```
/// {@endtemplate}
///
/// {@macro webview_fluttter.navigation_delegate.constructor}
NavigationDelegate.fromPlatformCreationParams(
PlatformNavigationDelegateCreationParams params, {
FutureOr<NavigationDecision> Function(NavigationRequest request)?
Expand All @@ -110,7 +110,7 @@ class NavigationDelegate {

/// Constructs a [NavigationDelegate] from a specific platform implementation.
///
/// {@macro webview_fluttter.navigation_delegate.constructor}
/// {@macro webview_fluttter.NavigationDelegate.constructor}
NavigationDelegate.fromPlatform(
this.platform, {
this.onNavigationRequest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,33 @@ import 'webview_widget.dart';
class WebViewController {
/// Constructs a [WebViewController].
///
/// {@template webview_fluttter.WebViewController.constructor}
/// `onPermissionRequest`: A callback that notifies the host application that
/// web content is requesting permission to access the specified resources.
/// To grant access for a device resource, most platforms will need to update
/// their app configurations for the relevant system resource.
///
/// For Android, you will need to update your `AndroidManifest.xml`. See
/// https://developer.android.com/training/permissions/declaring
///
/// For iOS, you will need to update your `Info.plist`. See
/// https://developer.apple.com/documentation/uikit/protecting_the_user_s_privacy/requesting_access_to_protected_resources?language=objc.
/// {@endtemplate}
///
/// See [WebViewController.fromPlatformCreationParams] for setting parameters
/// for a specific platform.
WebViewController()
: this.fromPlatformCreationParams(
WebViewController({
void Function(WebViewPermissionRequest request)? onPermissionRequest,
}) : this.fromPlatformCreationParams(
const PlatformWebViewControllerCreationParams(),
onPermissionRequest: onPermissionRequest,
);

/// Constructs a [WebViewController] from creation params for a specific
/// platform.
///
/// {@macro webview_fluttter.WebViewController.constructor}
///
/// {@template webview_flutter.WebViewController.fromPlatformCreationParams}
/// Below is an example of setting platform-specific creation parameters for
/// iOS and Android:
Expand Down Expand Up @@ -80,11 +97,31 @@ class WebViewController {
/// ```
/// {@endtemplate}
WebViewController.fromPlatformCreationParams(
PlatformWebViewControllerCreationParams params,
) : this.fromPlatform(PlatformWebViewController(params));
PlatformWebViewControllerCreationParams params, {
void Function(WebViewPermissionRequest request)? onPermissionRequest,
}) : this.fromPlatform(
PlatformWebViewController(params),
onPermissionRequest: onPermissionRequest,
);

/// Constructs a [WebViewController] from a specific platform implementation.
WebViewController.fromPlatform(this.platform);
///
/// {@macro webview_fluttter.WebViewController.constructor}
WebViewController.fromPlatform(
this.platform, {
void Function(WebViewPermissionRequest request)? onPermissionRequest,
}) {
if (onPermissionRequest != null) {
platform.setOnPlatformPermissionRequest(
(PlatformWebViewPermissionRequest request) {
onPermissionRequest(WebViewPermissionRequest._(
request,
types: request.types,
));
},
);
}
}

/// Implementation of [PlatformWebViewController] for the current platform.
final PlatformWebViewController platform;
Expand Down Expand Up @@ -319,3 +356,49 @@ class WebViewController {
return platform.setUserAgent(userAgent);
}
}

/// Permissions request when web content requests access to protected resources.
///
/// A response MUST be provided by calling [grant], [deny], or a method from
/// [platform].
///
/// ## Platform-Specific Features
/// This class contains an underlying implementation provided by the current
/// platform. Once a platform implementation is imported, the example below
/// can be followed to use features provided by a platform's implementation.
///
/// Below is an example of accessing the platform-specific implementation for
/// iOS and Android:
///
/// ```dart
/// final WebViewPermissionRequest request = ...;
///
/// if (WebViewPlatform.instance is WebKitWebViewPlatform) {
/// final WebKitWebViewPermissionRequest webKitRequest =
/// request.platform as WebKitWebViewPermissionRequest;
/// } else if (WebViewPlatform.instance is AndroidWebViewPlatform) {
/// final AndroidWebViewPermissionRequest androidRequest =
/// request.platform as AndroidWebViewPermissionRequest;
/// }
/// ```
@immutable
class WebViewPermissionRequest {
const WebViewPermissionRequest._(this.platform, {required this.types});

/// All resources access has been requested for.
final Set<WebViewPermissionResourceType> types;

/// Implementation of [PlatformWebViewPermissionRequest] for the current
/// platform.
final PlatformWebViewPermissionRequest platform;

/// Grant permission for the requested resource(s).
Future<void> grant() {
return platform.grant();
}

/// Deny permission for the requested resource(s).
Future<void> deny() {
return platform.deny();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ export 'package:webview_flutter_platform_interface/webview_flutter_platform_inte
PlatformNavigationDelegateCreationParams,
PlatformWebViewControllerCreationParams,
PlatformWebViewCookieManagerCreationParams,
PlatformWebViewPermissionRequest,
PlatformWebViewWidgetCreationParams,
ProgressCallback,
UrlChange,
WebResourceError,
WebResourceErrorCallback,
WebResourceErrorType,
WebViewCookie,
WebViewPermissionResourceType,
WebViewPlatform;

export 'src/navigation_delegate.dart';
Expand Down
4 changes: 2 additions & 2 deletions packages/webview_flutter/webview_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter
description: A Flutter plugin that provides a WebView widget on Android and iOS.
repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 4.1.0
version: 4.2.0

environment:
sdk: ">=2.18.0 <4.0.0"
Expand All @@ -20,7 +20,7 @@ dependencies:
flutter:
sdk: flutter
webview_flutter_android: ^3.0.0
webview_flutter_platform_interface: ^2.1.0
webview_flutter_platform_interface: ^2.3.0
webview_flutter_wkwebview: ^3.0.0

dev_dependencies:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,4 +365,38 @@ void main() {
mockPlatformNavigationDelegate,
));
});

test('onPermissionRequest', () async {
bool permissionRequestCallbackCalled = false;

final MockPlatformWebViewController mockPlatformWebViewController =
MockPlatformWebViewController();
WebViewController.fromPlatform(
mockPlatformWebViewController,
onPermissionRequest: (WebViewPermissionRequest request) {
permissionRequestCallbackCalled = true;
},
);

final void Function(PlatformWebViewPermissionRequest request)
requestCallback = verify(mockPlatformWebViewController
.setOnPlatformPermissionRequest(captureAny))
.captured
.single as void Function(PlatformWebViewPermissionRequest request);

requestCallback(const TestPlatformWebViewPermissionRequest());
expect(permissionRequestCallbackCalled, isTrue);
});
}

class TestPlatformWebViewPermissionRequest
extends PlatformWebViewPermissionRequest {
const TestPlatformWebViewPermissionRequest()
: super(types: const <WebViewPermissionResourceType>{});

@override
Future<void> grant() async {}

@override
Future<void> deny() async {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import 'package:webview_flutter_platform_interface/src/platform_navigation_deleg
as _i6;
import 'package:webview_flutter_platform_interface/src/platform_webview_controller.dart'
as _i4;
import 'package:webview_flutter_platform_interface/src/webview_platform.dart'
as _i2;
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i2;

// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
Expand Down Expand Up @@ -342,6 +341,18 @@ class MockPlatformWebViewController extends _i1.Mock
returnValue: _i5.Future<void>.value(),
returnValueForMissingStub: _i5.Future<void>.value(),
) as _i5.Future<void>);
@override
_i5.Future<void> setOnPlatformPermissionRequest(
void Function(_i2.PlatformWebViewPermissionRequest)?
onPermissionRequest) =>
(super.noSuchMethod(
Invocation.method(
#setOnPlatformPermissionRequest,
[onPermissionRequest],
),
returnValue: _i5.Future<void>.value(),
returnValueForMissingStub: _i5.Future<void>.value(),
) as _i5.Future<void>);
}

/// A class which mocks [PlatformNavigationDelegate].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import 'dart:async' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:webview_flutter_platform_interface/src/platform_webview_cookie_manager.dart'
as _i3;
import 'package:webview_flutter_platform_interface/src/webview_platform.dart'
as _i2;
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i2;

// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@ void main() {
// ignore: unnecessary_statements
main_file.PlatformWebViewCookieManagerCreationParams;
// ignore: unnecessary_statements
main_file.PlatformWebViewPermissionRequest;
// ignore: unnecessary_statements
main_file.PlatformWebViewWidgetCreationParams;
// ignore: unnecessary_statements
main_file.ProgressCallback;
// ignore: unnecessary_statements
main_file.WebViewPermissionResourceType;
// ignore: unnecessary_statements
main_file.WebResourceError;
// ignore: unnecessary_statements
main_file.WebResourceErrorCallback;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import 'package:webview_flutter_platform_interface/src/platform_webview_controll
as _i6;
import 'package:webview_flutter_platform_interface/src/platform_webview_widget.dart'
as _i9;
import 'package:webview_flutter_platform_interface/src/webview_platform.dart'
as _i2;
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i2;

// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
Expand Down Expand Up @@ -360,6 +359,18 @@ class MockPlatformWebViewController extends _i1.Mock
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<void> setOnPlatformPermissionRequest(
void Function(_i2.PlatformWebViewPermissionRequest)?
onPermissionRequest) =>
(super.noSuchMethod(
Invocation.method(
#setOnPlatformPermissionRequest,
[onPermissionRequest],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
}

/// A class which mocks [PlatformWebViewWidget].
Expand Down

0 comments on commit 2c0fc55

Please sign in to comment.