Skip to content

Commit 14a822f

Browse files
[webview_flutter_wkwebview] Webkit webview controller multiple registration fix (flutter#8078)
Fixes re-registering existing channels while removing Javascript channels in iOS environment. Android works as expected. Fixes flutter/flutter#158648
1 parent 7618126 commit 14a822f

4 files changed

Lines changed: 78 additions & 4 deletions

File tree

packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 3.16.3
2+
3+
* Fixes re-registering existing channels while removing Javascript channels.
4+
15
## 3.16.2
26

37
* Updates README to remove contributor-focused documentation.

packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -742,12 +742,16 @@ window.addEventListener("error", function(e) {
742742
_javaScriptChannelParams.keys.forEach(
743743
_webView.configuration.userContentController.removeScriptMessageHandler,
744744
);
745-
746-
_javaScriptChannelParams.remove(removedJavaScriptChannel);
745+
final Map<String, WebKitJavaScriptChannelParams> remainingChannelParams =
746+
Map<String, WebKitJavaScriptChannelParams>.from(
747+
_javaScriptChannelParams,
748+
);
749+
remainingChannelParams.remove(removedJavaScriptChannel);
750+
_javaScriptChannelParams.clear();
747751

748752
await Future.wait(<Future<void>>[
749753
for (final JavaScriptChannelParams params
750-
in _javaScriptChannelParams.values)
754+
in remainingChannelParams.values)
751755
addJavaScriptChannel(params),
752756
// Zoom is disabled with a WKUserScript, so this adds it back if it was
753757
// removed above.

packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: webview_flutter_wkwebview
22
description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control.
33
repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
5-
version: 3.16.2
5+
version: 3.16.3
66

77
environment:
88
sdk: ^3.5.0

packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,72 @@ void main() {
860860
verifyNoMoreInteractions(mockUserContentController);
861861
});
862862

863+
test('removeJavaScriptChannel multiple times', () async {
864+
final WebKitProxy webKitProxy = WebKitProxy(
865+
createScriptMessageHandler: ({
866+
required void Function(
867+
WKUserContentController userContentController,
868+
WKScriptMessage message,
869+
) didReceiveScriptMessage,
870+
}) {
871+
return WKScriptMessageHandler.detached(
872+
didReceiveScriptMessage: didReceiveScriptMessage,
873+
);
874+
},
875+
);
876+
877+
final WebKitJavaScriptChannelParams javaScriptChannelParams1 =
878+
WebKitJavaScriptChannelParams(
879+
name: 'name1',
880+
onMessageReceived: (JavaScriptMessage message) {},
881+
webKitProxy: webKitProxy,
882+
);
883+
884+
final WebKitJavaScriptChannelParams javaScriptChannelParams2 =
885+
WebKitJavaScriptChannelParams(
886+
name: 'name2',
887+
onMessageReceived: (JavaScriptMessage message) {},
888+
webKitProxy: webKitProxy,
889+
);
890+
891+
final MockWKUserContentController mockUserContentController =
892+
MockWKUserContentController();
893+
894+
final WebKitWebViewController controller = createControllerWithMocks(
895+
mockUserContentController: mockUserContentController,
896+
);
897+
898+
await controller.addJavaScriptChannel(javaScriptChannelParams1);
899+
await controller.addJavaScriptChannel(javaScriptChannelParams2);
900+
reset(mockUserContentController);
901+
902+
await controller.removeJavaScriptChannel('name1');
903+
904+
verify(mockUserContentController.removeAllUserScripts());
905+
verify(mockUserContentController.removeScriptMessageHandler('name1'));
906+
verify(mockUserContentController.removeScriptMessageHandler('name2'));
907+
908+
verify(mockUserContentController.addScriptMessageHandler(
909+
argThat(isA<WKScriptMessageHandler>()),
910+
'name2',
911+
));
912+
913+
final WKUserScript userScript =
914+
verify(mockUserContentController.addUserScript(captureAny))
915+
.captured
916+
.single as WKUserScript;
917+
expect(userScript.source, 'window.name2 = webkit.messageHandlers.name2;');
918+
expect(
919+
userScript.injectionTime,
920+
WKUserScriptInjectionTime.atDocumentStart,
921+
);
922+
923+
await controller.removeJavaScriptChannel('name2');
924+
verify(mockUserContentController.removeAllUserScripts());
925+
verify(mockUserContentController.removeScriptMessageHandler('name2'));
926+
verifyNoMoreInteractions(mockUserContentController);
927+
});
928+
863929
test('removeJavaScriptChannel with zoom disabled', () async {
864930
final WebKitProxy webKitProxy = WebKitProxy(
865931
createScriptMessageHandler: ({

0 commit comments

Comments
 (0)