-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
What package does this bug report belong to?
webview_flutter
What target platforms are you seeing this bug on?
iOS
Have you already upgraded your packages?
Yes
Dependency versions
pubspec.lock
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
characters:
dependency: transitive
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.dev"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev"
source: hosted
version: "1.18.0"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
version: "1.0.8"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
matcher:
dependency: transitive
description:
name: matcher
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev"
source: hosted
version: "0.12.16+1"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
version: "1.15.0"
path:
dependency: transitive
description:
name: path
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev"
source: hosted
version: "1.9.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.8"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
version: "2.1.2"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.dev"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.5"
webview_flutter:
dependency: "direct main"
description:
name: webview_flutter
sha256: "889a0a678e7c793c308c68739996227c9661590605e70b1f6cf6b9a6634f7aec"
url: "https://pub.dev"
source: hosted
version: "4.10.0"
webview_flutter_android:
dependency: transitive
description:
name: webview_flutter_android
sha256: "86c2d01c37c4578ee46560109cf2e18fb271f0d080a796f09188d0952352e057"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d
url: "https://pub.dev"
source: hosted
version: "2.10.0"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
sha256: "3be297aa4ca78205abdd284cf55f168c35246c75b3079990ad8ba9d257681a30"
url: "https://pub.dev"
source: hosted
version: "3.16.2"
sdks:
dart: ">=3.5.3 <4.0.0"
flutter: ">=3.24.0"
Steps to reproduce
- Initialize the WebViewController and call
addJavaScriptChannelfor 2 different channels:channel1,channel2. - In dispose function, call
removeJavaScriptChannelforchannel1andchannel2one after another. - It will throw the following exception:
A JavaScriptChannel with namechannel2already exists.
Expected results
When removing the java script channels from the webview controller in iOS, requested channels should be removed as expected without exception.
Root Cause
removeJavaScriptChannel function internally calls _resetUserScripts in the webkit_webview_controller.dart file. Since WKWebView does not support removing a single user script, all user scripts and all message handlers are removed instead. And the JavaScrip channels that shouldn't be removed are re-registered.
the following line clears the channel name from the internal map: _javaScriptChannelParams.remove(removedJavaScriptChannel); --> At this point _javaScriptChannelParams still have other channels' names.
Then the following function is being called:
for (final JavaScriptChannelParams params
in _javaScriptChannelParams.values)
addJavaScriptChannel(params)
all the channel names stored in the _javaScriptChannelParams map will be added again. Previously only one of them was removed.
Solution
Future<void> _resetUserScripts({String? removedJavaScriptChannel}) async {
unawaited(
_webView.configuration.userContentController.removeAllUserScripts(),
);
_javaScriptChannelParams.keys.forEach(
_webView.configuration.userContentController.removeScriptMessageHandler,
);
final params = Map<String, WebKitJavaScriptChannelParams>.from(
_javaScriptChannelParams);
params.remove(removedJavaScriptChannel);
_javaScriptChannelParams.clear();
await Future.wait(<Future<void>>[
for (final JavaScriptChannelParams params
in params.values)
addJavaScriptChannel(params),
// Zoom is disabled with a WKUserScript, so this adds it back if it was
// removed above.
if (!_zoomEnabled) _disableZoom(),
// Console logs are forwarded with a WKUserScript, so this adds it back
// if a console callback was registered with [setOnConsoleMessage].
if (_onConsoleMessageCallback != null) _injectConsoleOverride(),
]);
}
Actual results
Removing more than 1 JavaScriptChannel from WebviewController throws exception:
A JavaScriptChannel with name '<channelName>' already exists.
Code sample
Code sample
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const WebViewPage(),
),
);
},
child: const Text('Open WebView'),
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class WebViewPage extends StatefulWidget {
const WebViewPage({super.key});
@override
State<WebViewPage> createState() => _WebViewPageState();
}
class _WebViewPageState extends State<WebViewPage> {
late WebViewController controller;
final channel1 = 'channel1';
final channel2 = 'channel2';
@override
void initState() {
super.initState();
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel('channel1', onMessageReceived: (_) {})
..addJavaScriptChannel('channel2', onMessageReceived: (_) {})
..loadRequest(Uri.parse('https://flutter.dev'));
}
@override
void dispose() {
controller
..removeJavaScriptChannel(channel1)
..removeJavaScriptChannel(channel2);
super.dispose();
}
@override
Widget build(BuildContext context) {
return WebViewWidget(
controller: controller,
);
}
}
Screenshots or Videos
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): A JavaScriptChannel with name `channel2` already exists.
#0 WebKitWebViewController.addJavaScriptChannel (package:webview_flutter_wkwebview/src/webkit_webview_controller.dart:385:7)
#1 WebKitWebViewController._resetUserScripts (package:webview_flutter_wkwebview/src/webkit_webview_controller.dart:751:9)
#2 WebKitWebViewController.removeJavaScriptChannel (package:webview_flutter_wkwebview/src/webkit_webview_controller.dart:419:11)
#3 WebViewController.removeJavaScriptChannel (package:webview_flutter/src/webview_controller.dart:306:21)
#4 _WebViewPageState.dispose (package:bug/main.dart:73:9)
#5 StatefulElement.unmount (package:flutter/src/widgets/framework.dart:5826:11)
#6 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2077:13)
#7 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:2075:7)
#8 SingleChildR<…>Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.24.3, on macOS 13.6 22G120 darwin-arm64, locale en-DE)
• Flutter version 3.24.3 on channel stable at /Users/m.cakir.3/fvm/versions/3.24.3
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 2663184aa7 (9 weeks ago), 2024-09-11 16:27:48 -0500
• Engine revision 36335019a8
• Dart version 3.5.3
• DevTools version 2.37.3
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
• Android SDK at /Users/m.cakir.3/Library/Android/sdk
• Platform android-34, build-tools 34.0.0
• Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 15C500b
• CocoaPods version 1.14.3
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2022.3)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
[✓] VS Code (version 1.95.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension can be installed from:
🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (2 available)
• sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 13 (API 33) (emulator)
• iPhone 15 Plus (mobile) • B807136D-099D-499A-87D1-B19742BD406F • ios • com.apple.CoreSimulator.SimRuntime.iOS-17-0 (simulator)
[✓] Network resources
• All expected network resources are available.
• No issues found!