-
Notifications
You must be signed in to change notification settings - Fork 30.1k
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: productionIssues experienced in live production appsIssues experienced in live production appsc: crashStack traces logged to the consoleStack traces logged to the consoleneeds repro infoAutomated crash report whose cause isn't yet knownAutomated crash report whose cause isn't yet knownp: webviewThe WebView pluginThe WebView pluginpackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-iosiOS applications specificallyiOS applications specificallyteam-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem team
Description
What package does this bug report belong to?
webview_flutter_wkwebview
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:
meta:
dependency: "direct main"
description:
name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
version: "1.15.0"
path:
dependency: "direct dev"
description:
name: path
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev"
source: hosted
version: "1.9.0"
plugin_platform_interface:
dependency: "direct dev"
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.8"
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: "285cedfd9441267f6cca8843458620b5fda1af75b04f5818d0441acda5d7df19"
url: "https://pub.dev"
source: hosted
version: "4.1.0"
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: bf0745adeaca48a3105473440cffade47720fe2d56514de4e86f0d363439c4a7
url: "https://pub.dev"
source: hosted
version: "3.18.6"
sdks:
dart: ">=3.5.3 <4.0.0"
flutter: ">=3.24.0"
Steps to reproduce
We haven’t been able to reproduce it locally so far. However, we’ve observed a spike in this crash, particularly on iOS 18, though it’s not limited to that version.
Expected results
Not to crash
Actual results
Crash happens on iOS.
Code sample
Code sample
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:help_center/src/data/model/help_center_message_mapper.dart';
import 'package:help_center/src/data/model/help_center_message_model.dart';
import 'package:help_center/src/di/constants/help_center_constants.dart';
import 'package:help_center/src/presentation/screen/help_center_home_screen/widgets/help_center_image_upload_option_dialog.dart';
import 'package:help_center/src/presentation/screen/help_center_home_screen/widgets/help_center_loading_widget.dart';
import 'package:help_center/src/presentation/screen/help_center_home_screen/widgets/help_center_webview/bloc/help_center_webview_bloc.dart';
import 'package:help_center/src/presentation/screen/help_center_home_screen/widgets/help_center_webview/bloc/help_center_webview_event.dart';
import 'package:help_center/src/presentation/screen/help_center_home_screen/widgets/help_center_webview/bloc/help_center_webview_state.dart';
import 'package:help_center/src/presentation/utils/help_center_file_picker.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart'
as webview_flutter_android;
class HelpCenterWebViewWidget extends StatefulWidget {
final bool shouldApplyFreezeIssueWorkaround;
final String url;
const HelpCenterWebViewWidget({
required this.shouldApplyFreezeIssueWorkaround,
required this.url,
});
@override
_HelpCenterWebViewState createState() => _HelpCenterWebViewState();
}
class _HelpCenterWebViewState extends State<HelpCenterWebViewWidget> {
late HelpCenterWebViewBloc _bloc;
late Stopwatch _stopwatch;
bool isLoadingTimeAlreadyReported = false;
final WebViewController controller = WebViewController();
@override
void initState() {
super.initState();
_stopwatch = Stopwatch()..start();
if (Platform.isAndroid) {
final platformController = controller.platform
as webview_flutter_android.AndroidWebViewController;
platformController.setOnShowFileSelector(_showFileSelector);
}
controller
..setJavaScriptMode(JavaScriptMode.unrestricted)
..enableZoom(false) // Disabling zoom on webview
..loadRequest(Uri.parse(widget.url))
..addJavaScriptChannel(
HelpCenterConstants.bridgeEntry(),
onMessageReceived: (JavaScriptMessage message) async =>
_onMessageReceived(message, controller),
);
}
@override
Widget build(BuildContext context) {
_bloc = BlocProvider.of<HelpCenterWebViewBloc>(context);
return Scaffold(
body: BlocConsumer<HelpCenterWebViewBloc, HelpCenterWebViewState>(
buildWhen: _buildWhen,
listenWhen: _listenWhen,
builder: _onStateChangeBuilder,
listener: _onStateChangeListener,
),
);
}
bool _buildWhen(
HelpCenterWebViewState previous,
HelpCenterWebViewState current,
) {
return current is HelpCenterWebViewLoadingState ||
current is HelpCenterWebViewLoadedState;
}
bool _listenWhen(
HelpCenterWebViewState previous,
HelpCenterWebViewState current,
) {
return current is HelpCenterWebViewDeeplinkNavigationState;
}
Widget _onStateChangeBuilder(
BuildContext context,
HelpCenterWebViewState state,
) {
return SafeArea(
child: PopScope(
key: const Key("help_center_popscope_widget"),
canPop: _shouldAllowSwipingBack(state),
child: Stack(
children: [
Offstage(
key: const Key("help_center_webview_offstage_widget"),
offstage: _shouldHideWebView(state),
child: WebViewWidget(
key: const Key("help_center_webview_widget"),
controller: controller,
),
),
if (state is HelpCenterWebViewLoadingState)
const HelpCenterLoadingWidget(),
],
),
),
);
}
bool _shouldAllowSwipingBack(HelpCenterWebViewState state) {
// Only check loading state, if we should apply the workaround
if (widget.shouldApplyFreezeIssueWorkaround) {
return state is HelpCenterWebViewLoadingState;
}
// If no need to apply the fix (e.g older iOS versions than iOS 18), always make it swipeable
return true;
}
bool _shouldHideWebView(HelpCenterWebViewState state) {
// Only check loading state, if we should apply the workaround
if (widget.shouldApplyFreezeIssueWorkaround) {
return state is HelpCenterWebViewLoadingState;
}
// If no need to apply the fix (e.g older iOS versions than iOS 18), always show the web view even while loading.
return false;
}
Future<void> _onStateChangeListener(
BuildContext context,
HelpCenterWebViewState state,
) async {
if (state is HelpCenterWebViewDeeplinkNavigationState) {
await _navigate(state.deeplink);
}
}
Future<void> _onMessageReceived(
JavaScriptMessage message,
WebViewController controller,
) async {
final HelpCenterMessageResponse? helpCenterMessageResponseModel =
HelpCenterMessageMapper.map(message.message);
if (helpCenterMessageResponseModel == null) {
return;
}
if (helpCenterMessageResponseModel is! HelpCenterMessageResponseModel) {
return;
}
if (helpCenterMessageResponseModel.type ==
HelpCenterConstants.helpCenterClientCriticalContentRendered) {
if (!isLoadingTimeAlreadyReported) {
_reportLoadingTime();
}
_triggerLoadedEvent();
}
if (helpCenterMessageResponseModel.type ==
HelpCenterConstants.helpCenterInitStartedMessage) {
_helpCenterInitStartedMessage(controller);
return;
}
if (helpCenterMessageResponseModel.type ==
HelpCenterConstants.helpCenterAsksForShutdownMessage) {
_helpCenterAskedForShutdown(controller);
return;
}
if (helpCenterMessageResponseModel.type ==
HelpCenterConstants.helpCenterDeeplinkClicked) {
await _helpCenterDeeplinkClicked(helpCenterMessageResponseModel);
return;
}
}
void _reportLoadingTime() {
isLoadingTimeAlreadyReported = true;
_stopwatch.stop();
_bloc.add(
HelpCenterWebViewReportLoadingTimeEvent(
timeTakenToLoad: _stopwatch.elapsedMilliseconds,
),
);
return;
}
void _triggerLoadedEvent() {
_bloc.add(HelpCenterWebViewLoadedEvent());
}
void _helpCenterInitStartedMessage(WebViewController webViewController) {
_bloc.add(HelpCenterWebViewInitStartedEvent());
final javascriptCode =
"${HelpCenterConstants.messageToSend()}(${HelpCenterConstants.helpCenterInitialBridgeMessage})";
webViewController.runJavaScript(
javascriptCode,
);
}
void _helpCenterAskedForShutdown(WebViewController webViewController) {
webViewController
.removeJavaScriptChannel(HelpCenterConstants.bridgeEntry());
Navigator.of(context).pop();
}
Future<void> _helpCenterDeeplinkClicked(
HelpCenterMessageResponseModel messageModel,
) async {
final Map<String, dynamic>? payload = messageModel.payload;
if (payload == null) {
return;
}
final String? deeplink = payload['link'];
if (deeplink == null) {
return;
}
_bloc.add(HelpCenterWebViewDeeplinkClickedEvent(deeplink: deeplink));
}
Future<List<String>> _showFileSelector(
webview_flutter_android.FileSelectorParams params,
) async {
final helpCenterFilePicker = HelpCenterFilePickerImpl();
if (params.acceptTypes.any((type) => type == 'image/*')) {
if (params.mode ==
webview_flutter_android.FileSelectorMode.openMultiple) {
final images = await helpCenterFilePicker.getImages();
return images;
} else {
final image =
await _createImageUploadOptionDialog(context, helpCenterFilePicker);
if (image == null) {
return [];
}
return [image];
}
} else {
final allowMultipleSelection = (params.mode ==
webview_flutter_android.FileSelectorMode.openMultiple);
final files = await helpCenterFilePicker.getFiles(
allowMultipleSelection: allowMultipleSelection,
);
return files;
}
}
Future<String?> _createImageUploadOptionDialog(
BuildContext context,
HelpCenterFilePicker helpCenterFilePicker,
) async {
final Completer<String?> completer = Completer<String?>();
showDialog<String?>(
context: context,
builder: (BuildContext context) {
return HelpCenterImageUploadOptionDialog(
helpCenterFilePicker: helpCenterFilePicker,
);
},
).then((result) {
completer.complete(result);
});
return completer.future;
}
Future<void> _navigate(String deeplink) async {
if (deeplink.startsWith(HelpCenterConstants.talabatDeeplink)) {
Navigator.of(context).pushNamed(deeplink);
} else if (await canLaunchUrl(Uri.parse(deeplink))) {
final uri = Uri.parse(deeplink);
await launchUrl(uri);
}
}
}
Logs
Logs
Fatal Exception: NSInternalInconsistencyException
0 CoreFoundation 0x2d5fc __exceptionPreprocess
1 libobjc.A.dylib 0x31244 objc_exception_throw
2 Foundation 0x82dec0 _userInfoForFileAndLine
3 Flutter 0x15420 -[FlutterEngine sendOnChannel:message:binaryReply:] + 1255 (FlutterEngine.mm:1255)
4 Flutter 0x5d3810 -[FlutterBinaryMessengerRelay sendOnChannel:message:binaryReply:] + 34 (FlutterBinaryMessengerRelay.mm:34)
5 Flutter 0x5d6428 -[FlutterBasicMessageChannel sendMessage:reply:] + 120 (FlutterChannels.mm:120)
6 webview_flutter_wkwebview 0x1509c WebKitLibraryPigeonInstanceManagerApi.removeStrongReference(identifier:completion:) + 357 (WebKitLibrary.g.swift:357)
7 webview_flutter_wkwebview 0x13df4 WebKitLibraryPigeonInternalFinalizer.__deallocating_deinit + 532 (WebKitLibrary.g.swift:532)
8 libswiftCore.dylib 0x3d817c _swift_release_dealloc
9 libswiftCore.dylib 0x3d9290 bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1>>::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int)
10 libobjc.A.dylib 0x53b0 _object_remove_associations
11 libobjc.A.dylib 0x4f5c objc_destructInstance
12 libobjc.A.dylib 0x4eec _objc_rootDealloc
13 UIKitCore 0x989ec -[UIResponder dealloc]
14 UIKitCore 0x9871c -[UIView dealloc]
15 WebKit 0x58dd18 (Missing UUID 7fd7e19e8e703e7d8133e5c310a242d1)
16 Foundation 0x199054 _NSKVOPerformWithDeallocatingObservable
17 Foundation 0x198d68 NSKVODeallocate
18 libobjc.A.dylib 0x5bac object_cxxDestructFromClass(objc_object*, objc_class*)
19 libobjc.A.dylib 0x4f4c objc_destructInstance
20 libobjc.A.dylib 0x4eec _objc_rootDealloc
21 Flutter 0x365c0 std::_fl::__tree<std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>, std::_fl::__map_value_compare<long long, std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>, std::_fl::less<long long>, true>, std::_fl::allocator<std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>>>::destroy(std::_fl::__tree_node<std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>, void*>*) + 133 (new.cpp:133)
22 Flutter 0x365b4 std::_fl::__tree<std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>, std::_fl::__map_value_compare<long long, std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>, std::_fl::less<long long>, true>, std::_fl::allocator<std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>>>::destroy(std::_fl::__tree_node<std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>, void*>*) + 86 (scoped_typeref.h:86)
23 Flutter 0x365b4 std::_fl::__tree<std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>, std::_fl::__map_value_compare<long long, std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>, std::_fl::less<long long>, true>, std::_fl::allocator<std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>>>::destroy(std::_fl::__tree_node<std::_fl::__value_type<long long, fml::scoped_nsobject<NSObject<FlutterPlatformView>>>, void*>*) + 86 (scoped_typeref.h:86)
24 Flutter 0x19b38 std::_fl::__shared_ptr_pointer<flutter::FlutterPlatformViewsController*, std::_fl::shared_ptr<flutter::FlutterPlatformViewsController>::__shared_ptr_default_delete<flutter::FlutterPlatformViewsController, flutter::FlutterPlatformViewsController>, std::_fl::allocator<flutter::FlutterPlatformViewsController>>::__on_zero_shared() + 1087 (__tree:1087)
25 Flutter 0x122c0 -[FlutterEngine destroyContext] + 74 (atomic_support.h:74)
26 CoreFoundation 0x4e488 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__
27 CoreFoundation 0x4e3a4 ___CFXRegistrationPost_block_invoke
28 CoreFoundation 0x4cf18 _CFXRegistrationPost
29 CoreFoundation 0x4c01c _CFXNotificationPost
30 Foundation 0x9fa9c -[NSNotificationCenter postNotificationName:object:userInfo:]
31 UIKitCore 0x115c528 -[UIApplication _terminateWithStatus:]
32 UIKitCore 0x1b5644 -[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]
33 UIKitCore 0x906e8c -[_UISceneLifecycleMultiplexer forceExitWithTransitionContext:scene:]
34 UIKitCore 0x1157c28 -[UIApplication workspaceShouldExit:withTransitionContext:]
35 FrontBoardServices 0x56cd4 __63-[FBSWorkspaceScenesClient willTerminateWithTransitionContext:]_block_invoke_2
36 FrontBoardServices 0x1f4c8 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:]
37 FrontBoardServices 0x56c74 __63-[FBSWorkspaceScenesClient willTerminateWithTransitionContext:]_block_invoke
38 libdispatch.dylib 0x3fa8 _dispatch_client_callout
39 libdispatch.dylib 0x79f0 _dispatch_block_invoke_direct
40 FrontBoardServices 0x18378 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__
41 FrontBoardServices 0x182f8 -[FBSMainRunLoopSerialQueue _targetQueue_performNextIfPossible]
42 FrontBoardServices 0x181d0 -[FBSMainRunLoopSerialQueue _performNextFromRunLoopSource]
43 CoreFoundation 0x73f4c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
44 CoreFoundation 0x73ee0 __CFRunLoopDoSource0
45 CoreFoundation 0x76ba4 __CFRunLoopDoSources0
46 CoreFoundation 0x75d3c __CFRunLoopRun
47 CoreFoundation 0xc8284 CFRunLoopRunSpecific
48 GraphicsServices 0x14c0 GSEventRunModal
49 UIKitCore 0x3ee674 -[UIApplication _run]
50 UIKitCore 0x14e88 UIApplicationMain
51 UIKitCore 0x75115c keypath_get_selector_hoverStyle
52 Runner 0x2db6c main (StandaloneAppDelegate.swift)
53 ??? 0x1bf839de8 (Missing)
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.24.5, on macOS 15.4 24E248 darwin-arm64, locale en-AE)
• Flutter version 3.24.5 on channel stable at /Users/omaralaa/fvm/versions/3.24.5
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision dec2ee5c1f (6 months ago), 2024-11-13 11:13:06 -0800
• Engine revision a18df97ca5
• Dart version 3.5.4
• DevTools version 2.37.3
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.1)
• Android SDK at /Users/omaralaa/Library/Android/sdk
• Platform android-35, build-tools 35.0.1
• ANDROID_HOME = /Users/omaralaa/Library/Android/sdk
• ANDROID_SDK_ROOT = /Users/omaralaa/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 16.3)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 16E140
• CocoaPods version 1.15.2
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2024.2)
• 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 21.0.5+-12932927-b750.29)
[✓] IntelliJ IDEA Community Edition (version 2023.3.8)
• IntelliJ at /Users/omaralaa/Applications/IntelliJ IDEA Community Edition.app
• Flutter plugin version 83.0.1
• Dart plugin version 233.15325.11
[✓] VS Code (version 1.98.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.108.0
[✓] Connected device (4 available)
• sdk gphone16k arm64 (mobile) • emulator-5554 • android-arm64 • Android 15 (API 35) (emulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 15.4 24E248 darwin-arm64
• Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin • macOS 15.4 24E248 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 136.0.7103.93
! Error: Browsing on the local area network for Omar’s iPhone. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
! Error: Browsing on the local area network for Nouran. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources
• All expected network resources are available.
• No issues found!
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: productionIssues experienced in live production appsIssues experienced in live production appsc: crashStack traces logged to the consoleStack traces logged to the consoleneeds repro infoAutomated crash report whose cause isn't yet knownAutomated crash report whose cause isn't yet knownp: webviewThe WebView pluginThe WebView pluginpackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-iosiOS applications specificallyiOS applications specificallyteam-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem team