From 6b8fbae5169bc4b3b2ff7906077a74fc8dd4e0ba Mon Sep 17 00:00:00 2001 From: Seungsoo Lee Date: Mon, 14 Sep 2026 13:41:19 +0900 Subject: [PATCH 1/6] [webview_flutter_tizen] Select the backend from the device platform version DefaultBackendForPlatform() read the TIZEN_API_VERSION environment variable, which carries the api-version the application declares in its tizen-manifest.xml, not the platform version of the device. Every example app in this repository declares 6.0, so the EWK backend was selected on every device regardless of its Tizen version; a Tizen 10.1 target that should have used the WV wrapper backend ran EWK instead. Read the platform version from system-info instead, following the same pattern webview_flutter_lwe and device_info_plus already use. Co-Authored-By: Claude Opus 5 (1M context) --- .../tizen/src/webview_backend_factory.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/tizen/src/webview_backend_factory.cc b/packages/webview_flutter/tizen/src/webview_backend_factory.cc index 361d6579a..befcd88ef 100644 --- a/packages/webview_flutter/tizen/src/webview_backend_factory.cc +++ b/packages/webview_flutter/tizen/src/webview_backend_factory.cc @@ -4,6 +4,8 @@ #include "webview_backend_factory.h" +#include + #include #include @@ -19,9 +21,15 @@ enum class BackendKind { kEwk, kEwkWrapper, kWvStandalone }; BackendKind DefaultBackendForPlatform() { int major = 0, minor = 0; - if (const char* value = std::getenv("TIZEN_API_VERSION")) { + char* value = nullptr; + int ret = system_info_get_platform_string( + "http://tizen.org/feature/platform.version", &value); + if (ret == SYSTEM_INFO_ERROR_NONE && value) { std::sscanf(value, "%d.%d", &major, &minor); } + if (value) { + free(value); + } if (major >= 11) { return BackendKind::kWvStandalone; } From a7ca056452c9c6e1222f30de0f068d876b1b01b1 Mon Sep 17 00:00:00 2001 From: Seungsoo Lee Date: Mon, 14 Sep 2026 13:41:35 +0900 Subject: [PATCH 2/6] [webview_flutter_tizen] Fix the WV request header hash type WvWebViewBackend::LoadUrlRequest built an Eina_Hash and passed it to wv_view_url_request_set, whose local typedef declared the parameter as an untyped void*. The WV library iterates that pointer as a GHashTable, so the compiler accepted the mismatch and the library walked an unrelated structure: request headers were never delivered, and the walk corrupted heap metadata, aborting the application later with "malloc_consolidate(): unaligned fastbin chunk detected". Build a GHashTable and declare the parameter as GHashTable* so the same mismatch cannot recur silently. The unused Eina.h and Evas.h includes are dropped with it. Co-Authored-By: Claude Opus 5 (1M context) --- .../tizen/src/wv_internal_api_binding.h | 4 ++-- .../tizen/src/wv_webview_backend.cc | 21 +++++-------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/packages/webview_flutter/tizen/src/wv_internal_api_binding.h b/packages/webview_flutter/tizen/src/wv_internal_api_binding.h index c358aec5f..4241a1af7 100644 --- a/packages/webview_flutter/tizen/src/wv_internal_api_binding.h +++ b/packages/webview_flutter/tizen/src/wv_internal_api_binding.h @@ -135,8 +135,8 @@ typedef bool (*WvViewFocusSetFnPtr)(wv_view_h view, int focused); typedef bool (*WvViewUrlSetFnPtr)(wv_view_h view, const char* url); typedef const char* (*WvViewUrlGetFnPtr)(wv_view_h view); typedef bool (*WvViewUrlRequestSetFnPtr)(wv_view_h view, const char* url, - wv_http_method_e method, void* headers, - const char* body); + wv_http_method_e method, + GHashTable* headers, const char* body); typedef bool (*WvViewHtmlStringLoadFnPtr)(wv_view_h view, const char* html, const char* base_url, const char* unreachable_url); diff --git a/packages/webview_flutter/tizen/src/wv_webview_backend.cc b/packages/webview_flutter/tizen/src/wv_webview_backend.cc index 7771b62b1..71ddcdfd3 100644 --- a/packages/webview_flutter/tizen/src/wv_webview_backend.cc +++ b/packages/webview_flutter/tizen/src/wv_webview_backend.cc @@ -4,12 +4,9 @@ #include "wv_webview_backend.h" -#include -#include #include #include -#include #include #include #include @@ -371,25 +368,17 @@ bool WvWebViewBackend::LoadUrlRequest( wv_method = WV_HTTP_METHOD_POST; } - Eina_Hash* wv_headers = eina_hash_new( - [](const void* key) -> unsigned int { - return key ? strlen(static_cast(key)) + 1 : 0; - }, - [](const void* key1, int key1_length, const void* key2, - int key2_length) -> int { - return strcmp(static_cast(key1), - static_cast(key2)); - }, - EINA_KEY_HASH(eina_hash_superfast), [](void* data) { free(data); }, 10); + GHashTable* wv_headers = + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); for (const auto& header : headers) { - eina_hash_add(wv_headers, header.first.c_str(), - strdup(header.second.c_str())); + g_hash_table_insert(wv_headers, g_strdup(header.first.c_str()), + g_strdup(header.second.c_str())); } bool ret = WvInternalApiBinding::GetInstance().view.UrlRequestSet( view_, url.c_str(), wv_method, wv_headers, reinterpret_cast(body.data())); - eina_hash_free(wv_headers); + g_hash_table_destroy(wv_headers); return ret; } From 09d5a470fda1623a561bc4b813bcb77ebd201967 Mon Sep 17 00:00:00 2001 From: Seungsoo Lee Date: Mon, 14 Sep 2026 13:41:51 +0900 Subject: [PATCH 3/6] [webview_flutter_tizen] Correct the WV API declarations The WV function signatures are re-declared locally because the plugin reaches them through dlsym, and dlsym validates nothing. Comparing every bound symbol against the platform headers turned up two divergences besides the request header type: * wv_key_event_s was missing its trailing const char* device_name member, so wv_view_send_key_event read past the end of the stack-allocated struct. This is latent today because only the WV standalone path reads that field. * Nine function pointers declared an int return where the API returns bool or void. Co-Authored-By: Claude Opus 5 (1M context) --- .../tizen/src/wv_internal_api_binding.h | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/webview_flutter/tizen/src/wv_internal_api_binding.h b/packages/webview_flutter/tizen/src/wv_internal_api_binding.h index 4241a1af7..0ff53525d 100644 --- a/packages/webview_flutter/tizen/src/wv_internal_api_binding.h +++ b/packages/webview_flutter/tizen/src/wv_internal_api_binding.h @@ -94,6 +94,7 @@ typedef struct { wv_modifier_e modifiers; int event_flags; unsigned int key_code; + const char* device_name; } wv_key_event_s; typedef struct { @@ -163,10 +164,10 @@ typedef bool (*WvViewBgColorSetFnPtr)(wv_view_h view, int r, int g, int b, int a); typedef wv_context_h (*WvViewContextGetFnPtr)(wv_view_h view); typedef wv_settings_h (*WvViewSettingsGetFnPtr)(wv_view_h view); -typedef int (*WvViewFeedTouchEventFnPtr)(wv_view_h view, - wv_touch_event_type_e event_type, - GList* points, - wv_modifier_e modifiers); +typedef bool (*WvViewFeedTouchEventFnPtr)(wv_view_h view, + wv_touch_event_type_e event_type, + GList* points, + wv_modifier_e modifiers); typedef int (*WvViewFeedMouseDownFnPtr)(wv_view_h view, wv_mouse_button_type_e button, int x, int y); @@ -176,10 +177,10 @@ typedef int (*WvViewFeedMouseUpFnPtr)(wv_view_h view, typedef int (*WvViewFeedMouseMoveFnPtr)(wv_view_h view, int x, int y); typedef int (*WvViewFeedMouseWheelFnPtr)(wv_view_h view, bool y_direction, int step, int x, int y); -typedef int (*WvViewSendKeyEventFnPtr)(wv_view_h view, - const wv_key_event_s* key_event, - int is_press); -typedef int (*WvViewTouchEventsEnabledSetFnPtr)(wv_view_h view, int enabled); +typedef bool (*WvViewSendKeyEventFnPtr)(wv_view_h view, + const wv_key_event_s* key_event, + int is_press); +typedef bool (*WvViewTouchEventsEnabledSetFnPtr)(wv_view_h view, int enabled); typedef bool (*WvViewMouseEventsEnabledSetFnPtr)(wv_view_h view, bool enabled); typedef bool (*WvViewKeyEventsEnabledSetFnPtr)(wv_view_h view, bool enabled); typedef void (*WvViewImeWindowSetFnPtr)(wv_view_h view, void* window); @@ -257,10 +258,10 @@ typedef struct { typedef wv_cookie_manager_h (*WvContextCookieManagerGetFnPtr)( wv_context_h context); -typedef int (*WvContextCacheModelSetFnPtr)(wv_context_h context, - wv_cache_model_e model); -typedef int (*WvContextWebStorageDeleteAllFnPtr)(wv_context_h context); -typedef int (*WvContextCacheClearFnPtr)(wv_context_h context); +typedef bool (*WvContextCacheModelSetFnPtr)(wv_context_h context, + wv_cache_model_e model); +typedef bool (*WvContextWebStorageDeleteAllFnPtr)(wv_context_h context); +typedef bool (*WvContextCacheClearFnPtr)(wv_context_h context); typedef struct { WvContextCookieManagerGetFnPtr CookieManagerGet = nullptr; @@ -269,9 +270,9 @@ typedef struct { WvContextCacheClearFnPtr CacheClear = nullptr; } WvContextProcTable; -typedef int (*WvCookieManagerAcceptPolicySetFnPtr)( +typedef void (*WvCookieManagerAcceptPolicySetFnPtr)( wv_cookie_manager_h manager, wv_cookie_accept_policy_e policy); -typedef int (*WvCookieManagerCookiesClearFnPtr)(wv_cookie_manager_h manager); +typedef void (*WvCookieManagerCookiesClearFnPtr)(wv_cookie_manager_h manager); typedef struct { WvCookieManagerAcceptPolicySetFnPtr AcceptPolicySet = nullptr; @@ -301,7 +302,7 @@ typedef struct { WvErrorUrlGetFnPtr UrlGet = nullptr; } WvErrorProcTable; -typedef int (*WvPolicyDecisionUseFnPtr)(wv_policy_decision_h policy_decision); +typedef bool (*WvPolicyDecisionUseFnPtr)(wv_policy_decision_h policy_decision); typedef const char* (*WvPolicyDecisionUrlGetFnPtr)( wv_policy_decision_h policy_decision); typedef int (*WvPolicyDecisionResponseStatusCodeGetFnPtr)( From 110e6c88256fd3df7fcce780134590c7e52de45f Mon Sep 17 00:00:00 2001 From: Seungsoo Lee Date: Mon, 14 Sep 2026 13:42:10 +0900 Subject: [PATCH 4/6] [webview_flutter_tizen] Fix the cookie method channel lifetime The cookie method channel was created as a local in the WebView constructor and destroyed when the constructor returned, while the handler it installed on the messenger captured the WebView and outlived it. Nothing ever cleared that handler, and the channel name carried no view id, so a second WebView silently replaced the first one's handler and a cookie call after the last WebView was disposed reached freed memory. Register the channel once in the plugin, clear its handler in the plugin destructor, and route calls to the current WebView. ClearCookies gains a view check in both backends: the backend view is created lazily on the first WebView method call, so a cookie call that arrives before it passed a null view into the engine. Co-Authored-By: Claude Opus 5 (1M context) --- .../tizen/src/ewk_webview_backend.cc | 3 +++ packages/webview_flutter/tizen/src/webview.cc | 24 ++++++++++-------- packages/webview_flutter/tizen/src/webview.h | 7 ++++-- .../tizen/src/webview_flutter_tizen_plugin.cc | 25 ++++++++++++++++--- .../tizen/src/wv_webview_backend.cc | 3 +++ 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/packages/webview_flutter/tizen/src/ewk_webview_backend.cc b/packages/webview_flutter/tizen/src/ewk_webview_backend.cc index 95c825740..b83927b08 100644 --- a/packages/webview_flutter/tizen/src/ewk_webview_backend.cc +++ b/packages/webview_flutter/tizen/src/ewk_webview_backend.cc @@ -517,6 +517,9 @@ void EwkWebViewBackend::SetScrollbarVisible(bool visible) { } bool EwkWebViewBackend::ClearCookies() { + if (!view_) { + return false; + } Ewk_Context* context = ewk_view_context_get(view_); Ewk_Cookie_Manager* cookie_manager = ewk_context_cookie_manager_get(context); if (cookie_manager) { diff --git a/packages/webview_flutter/tizen/src/webview.cc b/packages/webview_flutter/tizen/src/webview.cc index a11fb07bd..b6112c269 100644 --- a/packages/webview_flutter/tizen/src/webview.cc +++ b/packages/webview_flutter/tizen/src/webview.cc @@ -27,6 +27,8 @@ constexpr char kTizenWebViewControllerChannelName[] = constexpr char kTizenNavigationDelegateChannelName[] = "plugins.flutter.io/tizen_webview_navigation_delegate_"; +WebView* g_current_webview = nullptr; + class NavigationRequestResult : public FlMethodResult { public: // |alive| gates every dereference below: Dart resolves this call @@ -128,14 +130,7 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int view_id, GetPluginRegistrar()->messenger(), GetNavigationDelegateChannelName(), &flutter::StandardMethodCodec::GetInstance()); - auto cookie_channel = std::make_unique( - GetPluginRegistrar()->messenger(), - "plugins.flutter.io/tizen_cookie_manager", - &flutter::StandardMethodCodec::GetInstance()); - cookie_channel->SetMethodCallHandler( - [webview = this](const auto& call, auto result) { - webview->HandleCookieMethodCall(call, std::move(result)); - }); + g_current_webview = this; } WebView::~WebView() { Dispose(); } @@ -164,6 +159,10 @@ void WebView::Dispose() { } *is_alive_ = false; + if (g_current_webview == this) { + g_current_webview = nullptr; + } + if (!backend_) { return; } @@ -523,7 +522,12 @@ void WebView::HandleWebViewMethodCall(const FlMethodCall& method_call, void WebView::HandleCookieMethodCall(const FlMethodCall& method_call, std::unique_ptr result) { - if (!webview_created_) { + WebView* webview = g_current_webview; + if (!webview) { + result->Error("Invalid operation", "No webview instance is available."); + return; + } + if (!webview->webview_created_) { result->Error("Invalid operation", "The webview instance has not been initialized."); return; @@ -532,7 +536,7 @@ void WebView::HandleCookieMethodCall(const FlMethodCall& method_call, const std::string& method_name = method_call.method_name(); if (method_name == "clearCookies") { - if (backend_->ClearCookies()) { + if (webview->backend_->ClearCookies()) { result->Success(flutter::EncodableValue(true)); } else { result->Error("Operation failed", "Failed to get cookie manager"); diff --git a/packages/webview_flutter/tizen/src/webview.h b/packages/webview_flutter/tizen/src/webview.h index efc0bebc5..8fa68fdd8 100644 --- a/packages/webview_flutter/tizen/src/webview.h +++ b/packages/webview_flutter/tizen/src/webview.h @@ -60,11 +60,14 @@ class WebView : public PlatformView, public WebViewBackend::Delegate { // Must be called exactly once, after every WebView has been destroyed. static void ShutdownEngine(); + // NOTE: Routes to the most recently created WebView, and fails once that one + // is disposed. + static void HandleCookieMethodCall(const FlMethodCall& method_call, + std::unique_ptr result); + private: void HandleWebViewMethodCall(const FlMethodCall& method_call, std::unique_ptr result); - void HandleCookieMethodCall(const FlMethodCall& method_call, - std::unique_ptr result); template void SetBackgroundColor(const T& color); diff --git a/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc b/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc index 5c663991c..a929651b0 100644 --- a/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc +++ b/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc @@ -5,6 +5,7 @@ #include "webview_flutter_tizen_plugin.h" #include +#include #include #include @@ -15,19 +16,37 @@ namespace { constexpr char kViewType[] = "plugins.flutter.io/webview"; +constexpr char kCookieManagerChannelName[] = + "plugins.flutter.io/tizen_cookie_manager"; // Constructed/destroyed exactly once by flutter-tizen's engine start/stop, // not per-WebView. class WebviewFlutterTizenPlugin : public flutter::Plugin { public: static void RegisterWithRegistrar(flutter::PluginRegistrar* registrar) { - auto plugin = std::make_unique(); + auto plugin = std::make_unique(registrar); registrar->AddPlugin(std::move(plugin)); } - WebviewFlutterTizenPlugin() { WebView::InitializeEngine(); } + explicit WebviewFlutterTizenPlugin(flutter::PluginRegistrar* registrar) { + WebView::InitializeEngine(); - virtual ~WebviewFlutterTizenPlugin() { WebView::ShutdownEngine(); } + cookie_channel_ = std::make_unique( + registrar->messenger(), kCookieManagerChannelName, + &flutter::StandardMethodCodec::GetInstance()); + cookie_channel_->SetMethodCallHandler( + [](const FlMethodCall& call, std::unique_ptr result) { + WebView::HandleCookieMethodCall(call, std::move(result)); + }); + } + + virtual ~WebviewFlutterTizenPlugin() { + cookie_channel_->SetMethodCallHandler(nullptr); + WebView::ShutdownEngine(); + } + + private: + std::unique_ptr cookie_channel_; }; } // namespace diff --git a/packages/webview_flutter/tizen/src/wv_webview_backend.cc b/packages/webview_flutter/tizen/src/wv_webview_backend.cc index 71ddcdfd3..b98485f7e 100644 --- a/packages/webview_flutter/tizen/src/wv_webview_backend.cc +++ b/packages/webview_flutter/tizen/src/wv_webview_backend.cc @@ -501,6 +501,9 @@ void WvWebViewBackend::SetScrollbarVisible(bool visible) { } bool WvWebViewBackend::ClearCookies() { + if (!view_) { + return false; + } auto& wv = WvInternalApiBinding::GetInstance(); wv_cookie_manager_h cookie_manager = wv.context.CookieManagerGet(wv.view.ContextGet(view_)); From fe925abd8e16bedaf3bad4211eee553c9b88a794 Mon Sep 17 00:00:00 2001 From: Seungsoo Lee Date: Wed, 16 Sep 2026 17:39:25 +0900 Subject: [PATCH 5/6] [webview_flutter_tizen] Update webview_flutter to 4.14.1 Update webview_flutter to 4.14.1 and webview_flutter_platform_interface to 2.15.1, raising the minimum supported SDK to Flutter 3.38/Dart 3.10. The only API added between 4.13.1 and 4.14.1 is WebViewCookieManager.getCookies. It throws UnimplementedError for now: the EWK cookie API returns nothing because of an engine defect being fixed, and the WV counterpart is not exported by the platform library. The example app follows upstream and lists cookies through getCookies rather than reading document.cookie. loadFileWithParams, added in platform_interface 2.14.0, needs no implementation: its base delegates to loadFile, which this package already provides. Co-Authored-By: Claude Opus 5 (1M context) --- packages/webview_flutter/CHANGELOG.md | 11 ++++++++-- packages/webview_flutter/README.md | 8 ++++++-- .../webview_flutter/example/lib/main.dart | 20 +++++++++++++------ packages/webview_flutter/example/pubspec.yaml | 6 +++--- .../lib/src/tizen_webview_cookie_manager.dart | 8 ++++++++ packages/webview_flutter/pubspec.yaml | 10 +++++----- 6 files changed, 45 insertions(+), 18 deletions(-) diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md index d3720af7f..66b36b80b 100644 --- a/packages/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/CHANGELOG.md @@ -1,5 +1,12 @@ -## NEXT - +## 0.11.1 + +* Update minimum supported SDK version to Flutter 3.38/Dart 3.10. +* Update webview_flutter to 4.14.1. +* Update webview_flutter_platform_interface to 2.15.1. +* Select the web engine backend from the device's platform version. +* Fix a crash and missing request headers on the WV backend. +* Fix cookie operations using a destroyed WebView. +* Correct the WV API declarations. * Omit obvious local variable types. * Reformat with a line length of 100. diff --git a/packages/webview_flutter/README.md b/packages/webview_flutter/README.md index 77e93a5ea..7991643ad 100644 --- a/packages/webview_flutter/README.md +++ b/packages/webview_flutter/README.md @@ -22,8 +22,8 @@ This package is not an _endorsed_ implementation of `webview_flutter`. Therefore ```yaml dependencies: - webview_flutter: ^4.13.1 - webview_flutter_tizen: ^0.11.0 + webview_flutter: ^4.14.1 + webview_flutter_tizen: ^0.11.1 ``` ## Example @@ -73,6 +73,10 @@ The plugin chooses a backend from the platform version reported by the device: The WV backends are experimental. `WebViewController.tizenEnginePolicy` has no WV equivalent, so it is ignored (with a warning) on Tizen 10.1 and later. +## Cookies + +- `WebViewCookieManager.getCookies` throws `UnimplementedError`: neither backend can read cookies yet. On the EWK backend the web engine's cookie API returns nothing, a defect being fixed; on the WV backends that API is not yet in the platform library. + ## Note - To play Youtube, make app's background color to transparent. diff --git a/packages/webview_flutter/example/lib/main.dart b/packages/webview_flutter/example/lib/main.dart index 51f13510e..24b76c313 100644 --- a/packages/webview_flutter/example/lib/main.dart +++ b/packages/webview_flutter/example/lib/main.dart @@ -433,8 +433,15 @@ class SampleMenu extends StatelessWidget { } Future _onListCookies(BuildContext context) async { - final cookies = - await webViewController.runJavaScriptReturningResult('document.cookie') as String; + final Uri? domain = Uri.tryParse((await webViewController.currentUrl()) ?? ''); + + final List cookies; + if (domain == null) { + cookies = []; + } else { + cookies = await cookieManager.getCookies(domain: domain); + } + if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -545,12 +552,13 @@ class SampleMenu extends StatelessWidget { return webViewController.loadHtmlString(kAlertTestPage); } - Widget _getCookieList(String cookies) { - if (cookies == '""') { + Widget _getCookieList(List cookies) { + if (cookies.isEmpty) { return Container(); } - final List cookieList = cookies.split(';'); - final Iterable cookieWidgets = cookieList.map((String cookie) => Text(cookie)); + final Iterable cookieWidgets = cookies.map( + (WebViewCookie cookie) => Text(cookie.toString()), + ); return Column( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, diff --git a/packages/webview_flutter/example/pubspec.yaml b/packages/webview_flutter/example/pubspec.yaml index 96c1b1238..a69dd78a9 100644 --- a/packages/webview_flutter/example/pubspec.yaml +++ b/packages/webview_flutter/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the webview_flutter_tizen plugin. publish_to: "none" environment: - sdk: ^3.8.0 - flutter: ">=3.32.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" dependencies: flutter: @@ -12,7 +12,7 @@ dependencies: path_provider: ^2.0.7 path_provider_tizen: path: ../../path_provider/ - webview_flutter: ^4.13.0 + webview_flutter: ^4.14.1 webview_flutter_tizen: path: ../ diff --git a/packages/webview_flutter/lib/src/tizen_webview_cookie_manager.dart b/packages/webview_flutter/lib/src/tizen_webview_cookie_manager.dart index c924f511a..3d502bfb5 100644 --- a/packages/webview_flutter/lib/src/tizen_webview_cookie_manager.dart +++ b/packages/webview_flutter/lib/src/tizen_webview_cookie_manager.dart @@ -21,6 +21,14 @@ class TizenWebViewCookieManager extends PlatformWebViewCookieManager { return await _cookieManagerChannel.invokeMethod('clearCookies') ?? false; } + @override + Future> getCookies(Uri url) { + throw UnimplementedError( + 'This version of `TizenWebViewCookieManager` currently has no ' + 'implementation for getCookies method.', + ); + } + @override Future setCookie(WebViewCookie cookie) async { if (!_isValidPath(cookie.path)) { diff --git a/packages/webview_flutter/pubspec.yaml b/packages/webview_flutter/pubspec.yaml index c0431e814..84fa834cc 100644 --- a/packages/webview_flutter/pubspec.yaml +++ b/packages/webview_flutter/pubspec.yaml @@ -2,11 +2,11 @@ name: webview_flutter_tizen description: Tizen implementation of the webview_flutter plugin. homepage: https://github.com/flutter-tizen/plugins repository: https://github.com/flutter-tizen/plugins/tree/main/packages/webview_flutter -version: 0.11.0 +version: 0.11.1 environment: - sdk: ^3.8.0 - flutter: ">=3.32.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" flutter: plugin: @@ -21,8 +21,8 @@ dependencies: flutter: sdk: flutter flutter_tizen: ^0.2.1 - webview_flutter: ^4.13.1 - webview_flutter_platform_interface: ^2.13.0 + webview_flutter: ^4.14.1 + webview_flutter_platform_interface: ^2.15.1 topics: - html From 2a32efec9b6ea38734c08745866551e44c0f3f16 Mon Sep 17 00:00:00 2001 From: Seungsoo Lee Date: Thu, 17 Sep 2026 16:08:29 +0900 Subject: [PATCH 6/6] [webview_flutter_tizen] Defer cookie channel changes to cookie branch --- packages/webview_flutter/CHANGELOG.md | 1 - .../tizen/src/ewk_webview_backend.cc | 3 --- packages/webview_flutter/tizen/src/webview.cc | 24 ++++++++---------- packages/webview_flutter/tizen/src/webview.h | 7 ++---- .../tizen/src/webview_flutter_tizen_plugin.cc | 25 +++---------------- .../tizen/src/wv_webview_backend.cc | 3 --- 6 files changed, 15 insertions(+), 48 deletions(-) diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md index 66b36b80b..be01c5163 100644 --- a/packages/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/CHANGELOG.md @@ -5,7 +5,6 @@ * Update webview_flutter_platform_interface to 2.15.1. * Select the web engine backend from the device's platform version. * Fix a crash and missing request headers on the WV backend. -* Fix cookie operations using a destroyed WebView. * Correct the WV API declarations. * Omit obvious local variable types. * Reformat with a line length of 100. diff --git a/packages/webview_flutter/tizen/src/ewk_webview_backend.cc b/packages/webview_flutter/tizen/src/ewk_webview_backend.cc index b83927b08..95c825740 100644 --- a/packages/webview_flutter/tizen/src/ewk_webview_backend.cc +++ b/packages/webview_flutter/tizen/src/ewk_webview_backend.cc @@ -517,9 +517,6 @@ void EwkWebViewBackend::SetScrollbarVisible(bool visible) { } bool EwkWebViewBackend::ClearCookies() { - if (!view_) { - return false; - } Ewk_Context* context = ewk_view_context_get(view_); Ewk_Cookie_Manager* cookie_manager = ewk_context_cookie_manager_get(context); if (cookie_manager) { diff --git a/packages/webview_flutter/tizen/src/webview.cc b/packages/webview_flutter/tizen/src/webview.cc index b6112c269..a11fb07bd 100644 --- a/packages/webview_flutter/tizen/src/webview.cc +++ b/packages/webview_flutter/tizen/src/webview.cc @@ -27,8 +27,6 @@ constexpr char kTizenWebViewControllerChannelName[] = constexpr char kTizenNavigationDelegateChannelName[] = "plugins.flutter.io/tizen_webview_navigation_delegate_"; -WebView* g_current_webview = nullptr; - class NavigationRequestResult : public FlMethodResult { public: // |alive| gates every dereference below: Dart resolves this call @@ -130,7 +128,14 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int view_id, GetPluginRegistrar()->messenger(), GetNavigationDelegateChannelName(), &flutter::StandardMethodCodec::GetInstance()); - g_current_webview = this; + auto cookie_channel = std::make_unique( + GetPluginRegistrar()->messenger(), + "plugins.flutter.io/tizen_cookie_manager", + &flutter::StandardMethodCodec::GetInstance()); + cookie_channel->SetMethodCallHandler( + [webview = this](const auto& call, auto result) { + webview->HandleCookieMethodCall(call, std::move(result)); + }); } WebView::~WebView() { Dispose(); } @@ -159,10 +164,6 @@ void WebView::Dispose() { } *is_alive_ = false; - if (g_current_webview == this) { - g_current_webview = nullptr; - } - if (!backend_) { return; } @@ -522,12 +523,7 @@ void WebView::HandleWebViewMethodCall(const FlMethodCall& method_call, void WebView::HandleCookieMethodCall(const FlMethodCall& method_call, std::unique_ptr result) { - WebView* webview = g_current_webview; - if (!webview) { - result->Error("Invalid operation", "No webview instance is available."); - return; - } - if (!webview->webview_created_) { + if (!webview_created_) { result->Error("Invalid operation", "The webview instance has not been initialized."); return; @@ -536,7 +532,7 @@ void WebView::HandleCookieMethodCall(const FlMethodCall& method_call, const std::string& method_name = method_call.method_name(); if (method_name == "clearCookies") { - if (webview->backend_->ClearCookies()) { + if (backend_->ClearCookies()) { result->Success(flutter::EncodableValue(true)); } else { result->Error("Operation failed", "Failed to get cookie manager"); diff --git a/packages/webview_flutter/tizen/src/webview.h b/packages/webview_flutter/tizen/src/webview.h index 8fa68fdd8..efc0bebc5 100644 --- a/packages/webview_flutter/tizen/src/webview.h +++ b/packages/webview_flutter/tizen/src/webview.h @@ -60,14 +60,11 @@ class WebView : public PlatformView, public WebViewBackend::Delegate { // Must be called exactly once, after every WebView has been destroyed. static void ShutdownEngine(); - // NOTE: Routes to the most recently created WebView, and fails once that one - // is disposed. - static void HandleCookieMethodCall(const FlMethodCall& method_call, - std::unique_ptr result); - private: void HandleWebViewMethodCall(const FlMethodCall& method_call, std::unique_ptr result); + void HandleCookieMethodCall(const FlMethodCall& method_call, + std::unique_ptr result); template void SetBackgroundColor(const T& color); diff --git a/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc b/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc index a929651b0..5c663991c 100644 --- a/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc +++ b/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc @@ -5,7 +5,6 @@ #include "webview_flutter_tizen_plugin.h" #include -#include #include #include @@ -16,37 +15,19 @@ namespace { constexpr char kViewType[] = "plugins.flutter.io/webview"; -constexpr char kCookieManagerChannelName[] = - "plugins.flutter.io/tizen_cookie_manager"; // Constructed/destroyed exactly once by flutter-tizen's engine start/stop, // not per-WebView. class WebviewFlutterTizenPlugin : public flutter::Plugin { public: static void RegisterWithRegistrar(flutter::PluginRegistrar* registrar) { - auto plugin = std::make_unique(registrar); + auto plugin = std::make_unique(); registrar->AddPlugin(std::move(plugin)); } - explicit WebviewFlutterTizenPlugin(flutter::PluginRegistrar* registrar) { - WebView::InitializeEngine(); + WebviewFlutterTizenPlugin() { WebView::InitializeEngine(); } - cookie_channel_ = std::make_unique( - registrar->messenger(), kCookieManagerChannelName, - &flutter::StandardMethodCodec::GetInstance()); - cookie_channel_->SetMethodCallHandler( - [](const FlMethodCall& call, std::unique_ptr result) { - WebView::HandleCookieMethodCall(call, std::move(result)); - }); - } - - virtual ~WebviewFlutterTizenPlugin() { - cookie_channel_->SetMethodCallHandler(nullptr); - WebView::ShutdownEngine(); - } - - private: - std::unique_ptr cookie_channel_; + virtual ~WebviewFlutterTizenPlugin() { WebView::ShutdownEngine(); } }; } // namespace diff --git a/packages/webview_flutter/tizen/src/wv_webview_backend.cc b/packages/webview_flutter/tizen/src/wv_webview_backend.cc index b98485f7e..71ddcdfd3 100644 --- a/packages/webview_flutter/tizen/src/wv_webview_backend.cc +++ b/packages/webview_flutter/tizen/src/wv_webview_backend.cc @@ -501,9 +501,6 @@ void WvWebViewBackend::SetScrollbarVisible(bool visible) { } bool WvWebViewBackend::ClearCookies() { - if (!view_) { - return false; - } auto& wv = WvInternalApiBinding::GetInstance(); wv_cookie_manager_h cookie_manager = wv.context.CookieManagerGet(wv.view.ContextGet(view_));