Skip to content

Commit b629b16

Browse files
committed
[webview_flutter_lwe] Fix "channel sent a message from native to Flutter on a non-platform thread" error
1 parent 5b0f1ed commit b629b16

File tree

4 files changed

+107
-35
lines changed

4 files changed

+107
-35
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2025 Samsung Electronics Co., Ltd. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "message_dispatcher.h"
6+
7+
#include <Ecore.h>
8+
9+
MessageDispatcher::MessageDispatcher() { ecore_init(); }
10+
MessageDispatcher::~MessageDispatcher() { ecore_shutdown(); }
11+
12+
void MessageDispatcher::dispatchTaskOnMainThread(std::function<void()> fn) {
13+
struct Param {
14+
std::function<void()> fn;
15+
};
16+
17+
Param* p = new Param;
18+
p->fn = fn;
19+
20+
ecore_main_loop_thread_safe_call_sync(
21+
[](void* data) -> void* {
22+
Param* p = (Param*)data;
23+
p->fn();
24+
delete p;
25+
return nullptr;
26+
},
27+
p);
28+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2025 Samsung Electronics Co., Ltd. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_PLUGIN_MESSAGE_DISPATCHER_H_
6+
#define FLUTTER_PLUGIN_MESSAGE_DISPATCHER_H_
7+
8+
#include <functional>
9+
10+
class MessageDispatcher {
11+
public:
12+
MessageDispatcher();
13+
~MessageDispatcher();
14+
15+
void dispatchTaskOnMainThread(std::function<void()> fn);
16+
};
17+
18+
#endif // FLUTTER_PLUGIN_MESSAGE_DISPATCHER_H_

packages/webview_flutter_lwe/tizen/src/webview.cc

Lines changed: 58 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int view_id,
125125

126126
InitWebView();
127127

128+
dispatcher = new MessageDispatcher();
129+
128130
webview_channel_ = std::make_unique<FlMethodChannel>(
129131
GetPluginRegistrar()->messenger(), GetWebViewChannelName(),
130132
&flutter::StandardMethodCodec::GetInstance());
@@ -148,53 +150,65 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int view_id,
148150

149151
webview_instance_->RegisterOnPageStartedHandler(
150152
[this](LWE::WebContainer* container, const std::string& url) {
151-
flutter::EncodableMap args = {
152-
{flutter::EncodableValue("url"), flutter::EncodableValue(url)}};
153-
navigation_delegate_channel_->InvokeMethod(
154-
"onPageStarted", std::make_unique<flutter::EncodableValue>(args));
153+
dispatcher->dispatchTaskOnMainThread([&]() {
154+
flutter::EncodableMap args = {
155+
{flutter::EncodableValue("url"), flutter::EncodableValue(url)}};
156+
navigation_delegate_channel_->InvokeMethod(
157+
"onPageStarted", std::make_unique<flutter::EncodableValue>(args));
158+
});
155159
});
156160
webview_instance_->RegisterOnPageLoadedHandler(
157161
[this](LWE::WebContainer* container, const std::string& url) {
158-
flutter::EncodableMap args = {
159-
{flutter::EncodableValue("url"), flutter::EncodableValue(url)}};
160-
navigation_delegate_channel_->InvokeMethod(
161-
"onPageFinished", std::make_unique<flutter::EncodableValue>(args));
162+
dispatcher->dispatchTaskOnMainThread([&]() {
163+
flutter::EncodableMap args = {
164+
{flutter::EncodableValue("url"), flutter::EncodableValue(url)}};
165+
navigation_delegate_channel_->InvokeMethod(
166+
"onPageFinished",
167+
std::make_unique<flutter::EncodableValue>(args));
168+
});
162169
});
163170
webview_instance_->RegisterOnProgressChangedHandler(
164171
[this](LWE::WebContainer* container, int progress) {
165-
flutter::EncodableMap args = {{flutter::EncodableValue("progress"),
166-
flutter::EncodableValue(progress)}};
167-
navigation_delegate_channel_->InvokeMethod(
168-
"onProgress", std::make_unique<flutter::EncodableValue>(args));
172+
dispatcher->dispatchTaskOnMainThread([&]() {
173+
flutter::EncodableMap args = {{flutter::EncodableValue("progress"),
174+
flutter::EncodableValue(progress)}};
175+
navigation_delegate_channel_->InvokeMethod(
176+
"onProgress", std::make_unique<flutter::EncodableValue>(args));
177+
});
169178
});
170179
webview_instance_->RegisterOnReceivedErrorHandler(
171180
[this](LWE::WebContainer* container, LWE::ResourceError error) {
172-
flutter::EncodableMap args = {
173-
{flutter::EncodableValue("errorCode"),
174-
flutter::EncodableValue(error.GetErrorCode())},
175-
{flutter::EncodableValue("description"),
176-
flutter::EncodableValue(error.GetDescription())},
177-
{flutter::EncodableValue("failingUrl"),
178-
flutter::EncodableValue(error.GetUrl())},
179-
};
180-
navigation_delegate_channel_->InvokeMethod(
181-
"onWebResourceError",
182-
std::make_unique<flutter::EncodableValue>(args));
181+
dispatcher->dispatchTaskOnMainThread([&]() {
182+
flutter::EncodableMap args = {
183+
{flutter::EncodableValue("errorCode"),
184+
flutter::EncodableValue(error.GetErrorCode())},
185+
{flutter::EncodableValue("description"),
186+
flutter::EncodableValue(error.GetDescription())},
187+
{flutter::EncodableValue("failingUrl"),
188+
flutter::EncodableValue(error.GetUrl())},
189+
};
190+
navigation_delegate_channel_->InvokeMethod(
191+
"onWebResourceError",
192+
std::make_unique<flutter::EncodableValue>(args));
193+
});
183194
});
184195
webview_instance_->RegisterShouldOverrideUrlLoadingHandler(
185196
[this](LWE::WebContainer* view, const std::string& url) -> bool {
186197
if (!has_navigation_delegate_) {
187198
return false;
188199
}
189-
flutter::EncodableMap args = {
190-
{flutter::EncodableValue("url"), flutter::EncodableValue(url)},
191-
{flutter::EncodableValue("isForMainFrame"),
192-
flutter::EncodableValue(true)},
193-
};
194-
auto result = std::make_unique<NavigationRequestResult>(url, this);
195-
navigation_delegate_channel_->InvokeMethod(
196-
"navigationRequest",
197-
std::make_unique<flutter::EncodableValue>(args), std::move(result));
200+
dispatcher->dispatchTaskOnMainThread([&]() {
201+
flutter::EncodableMap args = {
202+
{flutter::EncodableValue("url"), flutter::EncodableValue(url)},
203+
{flutter::EncodableValue("isForMainFrame"),
204+
flutter::EncodableValue(true)},
205+
};
206+
auto result = std::make_unique<NavigationRequestResult>(url, this);
207+
navigation_delegate_channel_->InvokeMethod(
208+
"navigationRequest",
209+
std::make_unique<flutter::EncodableValue>(args),
210+
std::move(result));
211+
});
198212
return true;
199213
});
200214
}
@@ -212,9 +226,11 @@ void WebView::RegisterJavaScriptChannelName(const std::string& name) {
212226
{flutter::EncodableValue("channel"), flutter::EncodableValue(name)},
213227
{flutter::EncodableValue("message"), flutter::EncodableValue(message)},
214228
};
215-
webview_channel_->InvokeMethod(
216-
"javaScriptChannelMessage",
217-
std::make_unique<flutter::EncodableValue>(args));
229+
dispatcher->dispatchTaskOnMainThread([&]() {
230+
webview_channel_->InvokeMethod(
231+
"javaScriptChannelMessage",
232+
std::make_unique<flutter::EncodableValue>(args));
233+
});
218234
return "success";
219235
};
220236
webview_instance_->AddJavaScriptInterface(name, "postMessage", on_message);
@@ -238,6 +254,11 @@ void WebView::Dispose() {
238254
webview_instance_->Destroy();
239255
webview_instance_ = nullptr;
240256
}
257+
258+
if (dispatcher) {
259+
delete dispatcher;
260+
dispatcher = nullptr;
261+
}
241262
}
242263

243264
void WebView::Resize(double width, double height) {
@@ -622,7 +643,9 @@ void WebView::HandleWebViewMethodCall(const FlMethodCall& method_call,
622643
delete result;
623644
}
624645
};
646+
625647
webview_instance_->EvaluateJavaScript(*javascript, on_result);
648+
626649
} else {
627650
result->Error("Invalid argument", "The argument must be a string.");
628651
}

packages/webview_flutter_lwe/tizen/src/webview.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <mutex>
1818
#include <string>
1919

20+
#include "message_dispatcher.h"
21+
2022
typedef flutter::MethodCall<flutter::EncodableValue> FlMethodCall;
2123
typedef flutter::MethodResult<flutter::EncodableValue> FlMethodResult;
2224
typedef flutter::MethodChannel<flutter::EncodableValue> FlMethodChannel;
@@ -66,6 +68,7 @@ class WebView : public PlatformView {
6668
void InitWebView();
6769

6870
LWE::WebContainer* webview_instance_ = nullptr;
71+
MessageDispatcher* dispatcher = nullptr;
6972
flutter::TextureRegistrar* texture_registrar_;
7073
double width_;
7174
double height_;

0 commit comments

Comments
 (0)