From 1ee29ab209aff5934a2241ef4206b55ff06f7575 Mon Sep 17 00:00:00 2001 From: Seungsoo Lee Date: Fri, 31 Jan 2025 18:10:01 +0900 Subject: [PATCH] Fix deadlock issue Calling setBackgroundColor() after the WebViewController is created causes a deadlock issue. --- packages/webview_flutter_lwe/CHANGELOG.md | 1 + .../webview_flutter_lwe/example/lib/main.dart | 26 +++----------- .../webview_flutter_lwe/example/pubspec.yaml | 2 -- .../tizen/src/message_dispatcher.cc | 23 ++++++++---- .../webview_flutter_lwe/tizen/src/webview.cc | 36 +++++++++++-------- .../webview_flutter_lwe/tizen/src/webview.h | 3 ++ 6 files changed, 48 insertions(+), 43 deletions(-) diff --git a/packages/webview_flutter_lwe/CHANGELOG.md b/packages/webview_flutter_lwe/CHANGELOG.md index b08298cef..dcfdf3161 100644 --- a/packages/webview_flutter_lwe/CHANGELOG.md +++ b/packages/webview_flutter_lwe/CHANGELOG.md @@ -4,6 +4,7 @@ * Update webview_flutter to 4.10.0. * Update webview_flutter_platform_interface to 2.10.0. * Add removeJavaScriptChannel method call. +* Fix deadlock issue caused by calling setBackgroundColor() after the WebViewController is created. ## 0.3.5 diff --git a/packages/webview_flutter_lwe/example/lib/main.dart b/packages/webview_flutter_lwe/example/lib/main.dart index 0264cf29e..a3507b23f 100644 --- a/packages/webview_flutter_lwe/example/lib/main.dart +++ b/packages/webview_flutter_lwe/example/lib/main.dart @@ -12,12 +12,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; import 'package:webview_flutter/webview_flutter.dart'; -// #docregion platform_imports -// Import for Android features. -import 'package:webview_flutter_android/webview_flutter_android.dart'; -// Import for iOS/macOS features. -import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; -// #enddocregion platform_imports void main() => runApp(const MaterialApp(home: WebViewExample())); @@ -122,14 +116,7 @@ class _WebViewExampleState extends State { // #docregion platform_features late final PlatformWebViewControllerCreationParams params; - if (WebViewPlatform.instance is WebKitWebViewPlatform) { - params = WebKitWebViewControllerCreationParams( - allowsInlineMediaPlayback: true, - mediaTypesRequiringUserAction: const {}, - ); - } else { - params = const PlatformWebViewControllerCreationParams(); - } + params = const PlatformWebViewControllerCreationParams(); final WebViewController controller = WebViewController.fromPlatformCreationParams(params); @@ -137,7 +124,7 @@ class _WebViewExampleState extends State { controller ..setJavaScriptMode(JavaScriptMode.unrestricted) - ..setBackgroundColor(const Color(0x80000000)) + ..setBackgroundColor(const Color(0x00000000)) ..setNavigationDelegate( NavigationDelegate( onProgress: (int progress) { @@ -190,13 +177,10 @@ Page resource error: ) ..loadRequest(Uri.parse('https://flutter.dev')); - // #docregion platform_features - if (controller.platform is AndroidWebViewController) { - AndroidWebViewController.enableDebugging(true); - (controller.platform as AndroidWebViewController) - .setMediaPlaybackRequiresUserGesture(false); + // setBackgroundColor is not currently supported on macOS. + if (kIsWeb || !Platform.isMacOS) { + controller.setBackgroundColor(const Color(0x80000000)); } - // #enddocregion platform_features _controller = controller; } diff --git a/packages/webview_flutter_lwe/example/pubspec.yaml b/packages/webview_flutter_lwe/example/pubspec.yaml index d89c2fa26..c16e87a21 100644 --- a/packages/webview_flutter_lwe/example/pubspec.yaml +++ b/packages/webview_flutter_lwe/example/pubspec.yaml @@ -13,10 +13,8 @@ dependencies: path_provider_tizen: path: ../../path_provider/ webview_flutter: ^4.10.0 - webview_flutter_android: ^4.0.0 webview_flutter_lwe: path: ../ - webview_flutter_wkwebview: ^3.13.0 dev_dependencies: flutter_driver: diff --git a/packages/webview_flutter_lwe/tizen/src/message_dispatcher.cc b/packages/webview_flutter_lwe/tizen/src/message_dispatcher.cc index 2d29d05b7..c6bc04c88 100644 --- a/packages/webview_flutter_lwe/tizen/src/message_dispatcher.cc +++ b/packages/webview_flutter_lwe/tizen/src/message_dispatcher.cc @@ -10,11 +10,22 @@ MessageDispatcher::MessageDispatcher() { ecore_init(); } MessageDispatcher::~MessageDispatcher() { ecore_shutdown(); } void MessageDispatcher::dispatchTaskOnMainThread(std::function&& fn) { - ecore_main_loop_thread_safe_call_sync( - [](void* data) -> void* { - auto fn = static_cast*>(data); - if (fn) (*fn)(); - return nullptr; + struct Param { + std::function fn; + }; + Param* p = new Param({std::move(fn)}); + + ecore_main_loop_thread_safe_call_async( + [](void* data) -> void { + ecore_timer_add( + 0.0, + [](void* data) -> Eina_Bool { + auto* p = static_cast(data); + p->fn(); + delete p; + return ECORE_CALLBACK_CANCEL; + }, + data); }, - &fn); + p); } diff --git a/packages/webview_flutter_lwe/tizen/src/webview.cc b/packages/webview_flutter_lwe/tizen/src/webview.cc index 089c08cea..7989a7ac6 100644 --- a/packages/webview_flutter_lwe/tizen/src/webview.cc +++ b/packages/webview_flutter_lwe/tizen/src/webview.cc @@ -153,7 +153,7 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int view_id, flutter::EncodableMap args = { {flutter::EncodableValue("url"), flutter::EncodableValue(url)}}; - dispatcher_->dispatchTaskOnMainThread([this, &args]() { + dispatcher_->dispatchTaskOnMainThread([this, args]() { navigation_delegate_channel_->InvokeMethod( "onPageStarted", std::make_unique(args)); }); @@ -163,7 +163,7 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int view_id, flutter::EncodableMap args = { {flutter::EncodableValue("url"), flutter::EncodableValue(url)}}; - dispatcher_->dispatchTaskOnMainThread([this, &args]() { + dispatcher_->dispatchTaskOnMainThread([this, args]() { navigation_delegate_channel_->InvokeMethod( "onPageFinished", std::make_unique(args)); @@ -174,7 +174,7 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int view_id, flutter::EncodableMap args = {{flutter::EncodableValue("progress"), flutter::EncodableValue(progress)}}; - dispatcher_->dispatchTaskOnMainThread([this, &args]() { + dispatcher_->dispatchTaskOnMainThread([this, args]() { navigation_delegate_channel_->InvokeMethod( "onProgress", std::make_unique(args)); }); @@ -189,8 +189,7 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int view_id, {flutter::EncodableValue("failingUrl"), flutter::EncodableValue(error.GetUrl())}, }; - - dispatcher_->dispatchTaskOnMainThread([this, &args]() { + dispatcher_->dispatchTaskOnMainThread([this, args]() { navigation_delegate_channel_->InvokeMethod( "onWebResourceError", std::make_unique(args)); @@ -207,7 +206,7 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int view_id, flutter::EncodableValue(true)}, }; - dispatcher_->dispatchTaskOnMainThread([this, &args, url]() { + dispatcher_->dispatchTaskOnMainThread([this, args, url]() { auto result = std::make_unique(url, this); navigation_delegate_channel_->InvokeMethod( "navigationRequest", @@ -231,7 +230,8 @@ void WebView::RegisterJavaScriptChannelName(const std::string& name) { {flutter::EncodableValue("channel"), flutter::EncodableValue(name)}, {flutter::EncodableValue("message"), flutter::EncodableValue(message)}, }; - dispatcher_->dispatchTaskOnMainThread([this, &args]() { + + dispatcher_->dispatchTaskOnMainThread([this, args]() { webview_channel_->InvokeMethod( "javaScriptChannelMessage", std::make_unique(args)); @@ -587,6 +587,14 @@ void WebView::InitWebView() { #endif } +template +void WebView::SetBackgroundColor(const T& color) { + LWE::Settings settings = webview_instance_->GetSettings(); + settings.SetBaseBackgroundColor(color >> 16 & 0xff, color >> 8 & 0xff, + color & 0xff, color >> 24 & 0xff); + webview_instance_->SetSettings(settings); +} + void WebView::HandleWebViewMethodCall(const FlMethodCall& method_call, std::unique_ptr result) { if (!webview_instance_) { @@ -735,15 +743,15 @@ void WebView::HandleWebViewMethodCall(const FlMethodCall& method_call, result->Error("Invalid argument", "The argument must be a string."); } } else if (method_name == "backgroundColor") { - const auto* color = std::get_if(arguments); - if (color) { - LWE::Settings settings = webview_instance_->GetSettings(); - settings.SetBaseBackgroundColor(*color >> 16 & 0xff, *color >> 8 & 0xff, - *color & 0xff, *color >> 24 & 0xff); - webview_instance_->SetSettings(settings); + if (std::holds_alternative(*arguments)) { + SetBackgroundColor(std::get(*arguments)); + result->Success(); + } else if (std::holds_alternative(*arguments)) { + SetBackgroundColor(std::get(*arguments)); result->Success(); } else { - result->Error("Invalid argument", "The argument must be a int64_t."); + result->Error("Invalid argument", + "The argument must be a int32_t or int64_t."); } } else if (method_name == "setUserAgent") { const auto* user_agent = std::get_if(arguments); diff --git a/packages/webview_flutter_lwe/tizen/src/webview.h b/packages/webview_flutter_lwe/tizen/src/webview.h index 9f96d8df2..eae0a6eab 100644 --- a/packages/webview_flutter_lwe/tizen/src/webview.h +++ b/packages/webview_flutter_lwe/tizen/src/webview.h @@ -61,6 +61,9 @@ class WebView : public PlatformView { void HandleCookieMethodCall(const FlMethodCall& method_call, std::unique_ptr result); + template + void SetBackgroundColor(const T& color); + void RegisterJavaScriptChannelName(const std::string& name); void UnregisterJavaScriptChannelName(const std::string& name); std::string GetWebViewChannelName();