Skip to content

Commit

Permalink
Fix deadlock issue
Browse files Browse the repository at this point in the history
Calling setBackgroundColor() after the WebViewController is created causes a deadlock issue.
  • Loading branch information
seungsoo47 committed Jan 31, 2025
1 parent 11673e8 commit 1ee29ab
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 43 deletions.
1 change: 1 addition & 0 deletions packages/webview_flutter_lwe/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
26 changes: 5 additions & 21 deletions packages/webview_flutter_lwe/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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()));

Expand Down Expand Up @@ -122,22 +116,15 @@ class _WebViewExampleState extends State<WebViewExample> {

// #docregion platform_features
late final PlatformWebViewControllerCreationParams params;
if (WebViewPlatform.instance is WebKitWebViewPlatform) {
params = WebKitWebViewControllerCreationParams(
allowsInlineMediaPlayback: true,
mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
);
} else {
params = const PlatformWebViewControllerCreationParams();
}
params = const PlatformWebViewControllerCreationParams();

final WebViewController controller =
WebViewController.fromPlatformCreationParams(params);
// #enddocregion platform_features

controller
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x80000000))
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 0 additions & 2 deletions packages/webview_flutter_lwe/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
23 changes: 17 additions & 6 deletions packages/webview_flutter_lwe/tizen/src/message_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,22 @@ MessageDispatcher::MessageDispatcher() { ecore_init(); }
MessageDispatcher::~MessageDispatcher() { ecore_shutdown(); }

void MessageDispatcher::dispatchTaskOnMainThread(std::function<void()>&& fn) {
ecore_main_loop_thread_safe_call_sync(
[](void* data) -> void* {
auto fn = static_cast<std::function<void()>*>(data);
if (fn) (*fn)();
return nullptr;
struct Param {
std::function<void()> 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<Param*>(data);
p->fn();
delete p;
return ECORE_CALLBACK_CANCEL;
},
data);
},
&fn);
p);
}
36 changes: 22 additions & 14 deletions packages/webview_flutter_lwe/tizen/src/webview.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<flutter::EncodableValue>(args));
});
Expand All @@ -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<flutter::EncodableValue>(args));
Expand All @@ -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<flutter::EncodableValue>(args));
});
Expand All @@ -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<flutter::EncodableValue>(args));
Expand All @@ -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<NavigationRequestResult>(url, this);
navigation_delegate_channel_->InvokeMethod(
"navigationRequest",
Expand All @@ -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<flutter::EncodableValue>(args));
Expand Down Expand Up @@ -587,6 +587,14 @@ void WebView::InitWebView() {
#endif
}

template <typename T>
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<FlMethodResult> result) {
if (!webview_instance_) {
Expand Down Expand Up @@ -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<int64_t>(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<int32_t>(*arguments)) {
SetBackgroundColor(std::get<int32_t>(*arguments));
result->Success();
} else if (std::holds_alternative<int64_t>(*arguments)) {
SetBackgroundColor(std::get<int64_t>(*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<std::string>(arguments);
Expand Down
3 changes: 3 additions & 0 deletions packages/webview_flutter_lwe/tizen/src/webview.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ class WebView : public PlatformView {
void HandleCookieMethodCall(const FlMethodCall& method_call,
std::unique_ptr<FlMethodResult> result);

template <typename T>
void SetBackgroundColor(const T& color);

void RegisterJavaScriptChannelName(const std::string& name);
void UnregisterJavaScriptChannelName(const std::string& name);
std::string GetWebViewChannelName();
Expand Down

0 comments on commit 1ee29ab

Please sign in to comment.