diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index b4fc793df82..a4ea405f961 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.18.5 + +* Fixes crash when sending undefined message via JavaScript channel. + ## 3.18.4 * Fixes crash when native `WKFrameInfo.request` is nil. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index 24e70d775b1..83a13e3d6bb 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -278,6 +278,47 @@ Future main() async { await expectLater(channelCompleter.future, completion('hello')); }); + testWidgets('JavaScriptChannel can receive undefined', + (WidgetTester tester) async { + final Completer pageFinished = Completer(); + final PlatformWebViewController controller = PlatformWebViewController( + const PlatformWebViewControllerCreationParams(), + ); + unawaited(controller.setJavaScriptMode(JavaScriptMode.unrestricted)); + final PlatformNavigationDelegate delegate = PlatformNavigationDelegate( + const PlatformNavigationDelegateCreationParams(), + ); + unawaited(delegate.setOnPageFinished((_) => pageFinished.complete())); + unawaited(controller.setPlatformNavigationDelegate(delegate)); + + final Completer channelCompleter = Completer(); + await controller.addJavaScriptChannel( + JavaScriptChannelParams( + name: 'Channel', + onMessageReceived: (JavaScriptMessage message) { + channelCompleter.complete(message.message); + }, + ), + ); + + await controller.loadHtmlString( + 'data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+', + ); + + await tester.pumpWidget(Builder( + builder: (BuildContext context) { + return PlatformWebViewWidget( + PlatformWebViewWidgetCreationParams(controller: controller), + ).build(context); + }, + )); + + await pageFinished.future; + + await controller.runJavaScript('Channel.postMessage(undefined);'); + await expectLater(channelCompleter.future, completion('(null)')); + }); + testWidgets('resize webview', (WidgetTester tester) async { final Completer buttonTapResizeCompleter = Completer(); final Completer onPageFinished = Completer(); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/weak_reference_utils.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/weak_reference_utils.dart index f12485ad6e7..014d9eb42ea 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/weak_reference_utils.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/weak_reference_utils.dart @@ -18,7 +18,7 @@ /// ) { /// weakReference.target?.onJavascriptChannelMessage( /// message.name, -/// message.body!.toString(), +/// message.body.toString(), /// ); /// }; /// }, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart index 016f1734b94..89e184a89a5 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart @@ -456,7 +456,7 @@ class WebKitWebViewPlatformController extends WebViewPlatformController { ) { weakReference.target?.onJavascriptChannelMessage( message.name, - message.body!.toString(), + message.body.toString(), ); }; }, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index 2ece1206dae..843c73f3de3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -905,8 +905,13 @@ class WebKitJavaScriptChannelParams extends JavaScriptChannelParams { (WeakReference weakReference) { return (_, __, WKScriptMessage message) { if (weakReference.target != null) { + // When message.body is null, return '(null)' for consistency + // with previous implementations. weakReference.target!( - JavaScriptMessage(message: message.body!.toString()), + JavaScriptMessage( + message: message.body == null + ? '(null)' + : message.body.toString()), ); } }; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index 5a0e7ed115a..67f2f644cd6 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.18.4 +version: 3.18.5 environment: sdk: ^3.5.0