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

[webview_flutter] Added Android implementation of PlatformWebViewWidget #6686

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';

import '../../android_webview.dart' as android_webview;
import '../../android_webview.dart';
import '../../instance_manager.dart';
import '../../weak_reference_utils.dart';
import 'android_navigation_delegate.dart';
import 'android_proxy.dart';
Expand Down Expand Up @@ -329,3 +333,87 @@ class AndroidJavaScriptChannelParams extends JavaScriptChannelParams {

final android_webview.JavaScriptChannel _javaScriptChannel;
}

/// Object specifying creation parameters for creating a [AndroidWebViewWidget].
///
/// When adding additional fields make sure they can be null or have a default
/// value to avoid breaking changes. See [PlatformWebViewWidgetCreationParams] for
/// more information.
@immutable
class AndroidWebViewWidgetCreationParams
extends PlatformWebViewWidgetCreationParams {
/// Creates [AndroidWebWidgetCreationParams].
AndroidWebViewWidgetCreationParams({
super.key,
required super.controller,
super.layoutDirection,
super.gestureRecognizers,
@visibleForTesting InstanceManager? instanceManager,
}) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager;

/// Constructs a [WebKitWebViewWidgetCreationParams] using a
/// [PlatformWebViewWidgetCreationParams].
AndroidWebViewWidgetCreationParams.fromPlatformWebViewWidgetCreationParams(
PlatformWebViewWidgetCreationParams params, {
InstanceManager? instanceManager,
}) : this(
key: params.key,
controller: params.controller,
layoutDirection: params.layoutDirection,
gestureRecognizers: params.gestureRecognizers,
instanceManager: instanceManager,
);

/// Maintains instances used to communicate with the native objects they
/// represent.
///
/// This field is exposed for testing purposes only and should not be used
/// outside of tests.
@visibleForTesting
final InstanceManager instanceManager;
}

/// An implementation of [PlatformWebViewWidget] with the Android WebView API.
class AndroidWebViewWidget extends PlatformWebViewWidget {
/// Constructs a [WebKitWebViewWidget].
AndroidWebViewWidget(PlatformWebViewWidgetCreationParams params)
: super.implementation(
params is AndroidWebViewWidgetCreationParams
? params
: AndroidWebViewWidgetCreationParams
.fromPlatformWebViewWidgetCreationParams(params),
);

AndroidWebViewWidgetCreationParams get _androidParams =>
params as AndroidWebViewWidgetCreationParams;

@override
Widget build(BuildContext context) {
return PlatformViewLink(
key: _androidParams.key,
viewType: 'plugins.flutter.io/webview',
surfaceFactory: (
BuildContext context,
PlatformViewController controller,
) {
return AndroidViewSurface(
controller: controller as AndroidViewController,
gestureRecognizers: _androidParams.gestureRecognizers,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
onCreatePlatformView: (PlatformViewCreationParams params) {
return PlatformViewsService.initSurfaceAndroidView(
id: params.id,
viewType: 'plugins.flutter.io/webview',
layoutDirection: _androidParams.layoutDirection,
creationParams: _androidParams.instanceManager.getIdentifier(
(_androidParams.controller as AndroidWebViewController)
._webView),
creationParamsCodec: const StandardMessageCodec(),
)
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
..create();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:webview_flutter_android/src/android_webview.dart'
as android_webview;
import 'package:webview_flutter_android/src/instance_manager.dart';
import 'package:webview_flutter_android/src/v4/src/android_navigation_delegate.dart';
import 'package:webview_flutter_android/src/v4/src/android_proxy.dart';
import 'package:webview_flutter_android/src/v4/src/android_webview_controller.dart';
Expand All @@ -18,80 +20,84 @@ import 'android_webview_controller_test.mocks.dart';

@GenerateNiceMocks(<MockSpec<Object>>[
MockSpec<AndroidNavigationDelegate>(),
MockSpec<AndroidWebViewController>(),
MockSpec<AndroidWebViewProxy>(),
MockSpec<AndroidWebViewWidgetCreationParams>(),
MockSpec<android_webview.FlutterAssetManager>(),
MockSpec<android_webview.JavaScriptChannel>(),
MockSpec<android_webview.WebChromeClient>(),
MockSpec<android_webview.WebSettings>(),
MockSpec<android_webview.WebView>(),
MockSpec<android_webview.WebViewClient>(),
MockSpec<android_webview.WebStorage>(),
MockSpec<BuildContext>(),
MockSpec<InstanceManager>(),
])
void main() {
TestWidgetsFlutterBinding.ensureInitialized();

group('AndroidWebViewController', () {
AndroidWebViewController createControllerWithMocks({
android_webview.FlutterAssetManager? mockFlutterAssetManager,
android_webview.JavaScriptChannel? mockJavaScriptChannel,
android_webview.WebChromeClient? mockWebChromeClient,
android_webview.WebView? mockWebView,
android_webview.WebViewClient? mockWebViewClient,
android_webview.WebStorage? mockWebStorage,
}) {
final android_webview.WebView nonNullMockWebView =
mockWebView ?? MockWebView();

final AndroidWebViewControllerCreationParams creationParams =
AndroidWebViewControllerCreationParams(
androidWebStorage: mockWebStorage ?? MockWebStorage(),
androidWebViewProxy: AndroidWebViewProxy(
createAndroidWebChromeClient: (
{void Function(android_webview.WebView, int)?
onProgressChanged}) =>
mockWebChromeClient ?? MockWebChromeClient(),
createAndroidWebView: ({required bool useHybridComposition}) =>
nonNullMockWebView,
createAndroidWebViewClient: ({
void Function(android_webview.WebView webView, String url)?
onPageFinished,
void Function(android_webview.WebView webView, String url)?
onPageStarted,
@Deprecated('Only called on Android version < 23.')
void Function(
android_webview.WebView webView,
int errorCode,
String description,
String failingUrl,
)?
onReceivedError,
void Function(
android_webview.WebView webView,
android_webview.WebResourceRequest request,
android_webview.WebResourceError error,
)?
onReceivedRequestError,
void Function(
android_webview.WebView webView,
android_webview.WebResourceRequest request,
)?
requestLoading,
void Function(android_webview.WebView webView, String url)?
urlLoading,
}) =>
mockWebViewClient ?? MockWebViewClient(),
createFlutterAssetManager: () =>
mockFlutterAssetManager ?? MockFlutterAssetManager(),
createJavaScriptChannel: (
String channelName, {
required void Function(String) postMessage,
}) =>
mockJavaScriptChannel ?? MockJavaScriptChannel(),
));

return AndroidWebViewController(creationParams);
}
AndroidWebViewController createControllerWithMocks({
android_webview.FlutterAssetManager? mockFlutterAssetManager,
android_webview.JavaScriptChannel? mockJavaScriptChannel,
android_webview.WebChromeClient? mockWebChromeClient,
android_webview.WebView? mockWebView,
android_webview.WebViewClient? mockWebViewClient,
android_webview.WebStorage? mockWebStorage,
}) {
final android_webview.WebView nonNullMockWebView =
mockWebView ?? MockWebView();

final AndroidWebViewControllerCreationParams creationParams =
AndroidWebViewControllerCreationParams(
androidWebStorage: mockWebStorage ?? MockWebStorage(),
androidWebViewProxy: AndroidWebViewProxy(
createAndroidWebChromeClient: (
{void Function(android_webview.WebView, int)?
onProgressChanged}) =>
mockWebChromeClient ?? MockWebChromeClient(),
createAndroidWebView: ({required bool useHybridComposition}) =>
nonNullMockWebView,
createAndroidWebViewClient: ({
void Function(android_webview.WebView webView, String url)?
onPageFinished,
void Function(android_webview.WebView webView, String url)?
onPageStarted,
@Deprecated('Only called on Android version < 23.')
void Function(
android_webview.WebView webView,
int errorCode,
String description,
String failingUrl,
)?
onReceivedError,
void Function(
android_webview.WebView webView,
android_webview.WebResourceRequest request,
android_webview.WebResourceError error,
)?
onReceivedRequestError,
void Function(
android_webview.WebView webView,
android_webview.WebResourceRequest request,
)?
requestLoading,
void Function(android_webview.WebView webView, String url)?
urlLoading,
}) =>
mockWebViewClient ?? MockWebViewClient(),
createFlutterAssetManager: () =>
mockFlutterAssetManager ?? MockFlutterAssetManager(),
createJavaScriptChannel: (
String channelName, {
required void Function(String) postMessage,
}) =>
mockJavaScriptChannel ?? MockJavaScriptChannel(),
));

return AndroidWebViewController(creationParams);
}

group('AndroidWebViewController', () {
AndroidJavaScriptChannelParams
createAndroidJavaScriptChannelParamsWithMocks({
String? name,
Expand Down Expand Up @@ -728,4 +734,31 @@ void main() {
verify(mockSettings.setUserAgentString('Test Framework')).called(1);
});
});

group('AndroidWebViewWidget', () {
testWidgets('Builds AndroidView using supplied parameters',
(WidgetTester tester) async {
final MockAndroidWebViewWidgetCreationParams mockParams =
MockAndroidWebViewWidgetCreationParams();
final MockInstanceManager mockInstanceManager = MockInstanceManager();
final MockWebView mockWebView = MockWebView();
final AndroidWebViewController controller =
createControllerWithMocks(mockWebView: mockWebView);

when(mockParams.key).thenReturn(const Key('test_web_view'));
when(mockParams.instanceManager).thenReturn(mockInstanceManager);
when(mockParams.controller).thenReturn(controller);
when(mockInstanceManager.getIdentifier(mockWebView)).thenReturn(42);

final AndroidWebViewWidget webViewWidget =
AndroidWebViewWidget(mockParams);

await tester.pumpWidget(Builder(
builder: (BuildContext context) => webViewWidget.build(context),
));

expect(find.byType(PlatformViewLink), findsOneWidget);
expect(find.byKey(const Key('test_web_view')), findsOneWidget);
});
});
}
Loading