From 1134cc059de9b574db37ae1f33f4295bad795f56 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Wed, 31 Jan 2024 11:23:50 +0530 Subject: [PATCH] [FEAT] Add Backwards compatibility to webkit2gtk-4.0 (#311) * feat: add fix for webkit2gtk 4.0 linux * Revert "fix linux webkit2gtk deprecated error (#246)" This reverts commit 0eeeb808160aa0f30d5e7ca8ba957fefe7de5f03. * fix: allow this plugin on both 4.0 and 4.1 webkit * fix: update README.md * chore: bump to v0.2.4 * fix: error on line 257 --- packages/desktop_webview_window/CHANGELOG.md | 4 + packages/desktop_webview_window/README.md | 2 +- .../linux/CMakeLists.txt | 6 +- .../linux/webview_window.cc | 228 +++++++++++------- packages/desktop_webview_window/pubspec.yaml | 2 +- 5 files changed, 149 insertions(+), 93 deletions(-) diff --git a/packages/desktop_webview_window/CHANGELOG.md b/packages/desktop_webview_window/CHANGELOG.md index 951e1d1b..f5464974 100644 --- a/packages/desktop_webview_window/CHANGELOG.md +++ b/packages/desktop_webview_window/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.4 + +* Add backward compatibility with webkit2gtk-4.0 on Linux + ## 0.2.3 * fix macOS webview window size not working. diff --git a/packages/desktop_webview_window/README.md b/packages/desktop_webview_window/README.md index 9b15ad15..748f2326 100644 --- a/packages/desktop_webview_window/README.md +++ b/packages/desktop_webview_window/README.md @@ -7,7 +7,7 @@ Show a webview window on your flutter desktop application. | | | | | -------- | ------- | ---- | | Windows | ✅ | [Webview2](https://www.nuget.org/packages/Microsoft.Web.WebView2) 1.0.992.28 | -| Linux | ✅ | [WebKitGTK-4.1](https://webkitgtk.org/reference/webkit2gtk/stable/index.html) | +| Linux | ✅ | [WebKitGTK-4.1](https://webkitgtk.org/reference/webkit2gtk/stable/index.html) or [WebKitGTK-4.0](https://webkitgtk.org/reference/webkit2gtk/2.5.1/) | | macOS | ✅ | WKWebview | ## Getting Started diff --git a/packages/desktop_webview_window/linux/CMakeLists.txt b/packages/desktop_webview_window/linux/CMakeLists.txt index f5d12ef4..8d71d5d0 100644 --- a/packages/desktop_webview_window/linux/CMakeLists.txt +++ b/packages/desktop_webview_window/linux/CMakeLists.txt @@ -7,7 +7,11 @@ project(${PROJECT_NAME} LANGUAGES CXX) set(PLUGIN_NAME "desktop_webview_window_plugin") find_package(PkgConfig REQUIRED) -pkg_check_modules(WebKit REQUIRED IMPORTED_TARGET webkit2gtk-4.1) +pkg_check_modules(WebKit IMPORTED_TARGET webkit2gtk-4.1) +if (NOT WebKit_FOUND) + add_compile_definitions(WEBKIT_OLD_USED=1) + pkg_check_modules(WebKit REQUIRED IMPORTED_TARGET webkit2gtk-4.0) # for backward compatibility +endif () add_library(${PLUGIN_NAME} SHARED "desktop_webview_window_plugin.cc" diff --git a/packages/desktop_webview_window/linux/webview_window.cc b/packages/desktop_webview_window/linux/webview_window.cc index fc8c176b..05a1263f 100644 --- a/packages/desktop_webview_window/linux/webview_window.cc +++ b/packages/desktop_webview_window/linux/webview_window.cc @@ -8,43 +8,48 @@ #include "message_channel_plugin.h" -namespace { - -gboolean on_load_failed_with_tls_errors( - WebKitWebView *web_view, - char *failing_uri, - GTlsCertificate *certificate, - GTlsCertificateFlags errors, - gpointer user_data) { - auto *webview = static_cast(user_data); - g_critical("on_load_failed_with_tls_errors: %s %p error= %d", failing_uri, webview, errors); - // TODO allow certificate for some certificate ? - // maybe we can use the pem from https://source.chromium.org/chromium/chromium/src/+/master:net/data/ssl/ev_roots/ -// webkit_web_context_allow_tls_certificate_for_host(webkit_web_view_get_context(web_view), certificate, uri->host); -// webkit_web_view_load_uri(web_view, failing_uri); - return false; -} +namespace +{ + + gboolean on_load_failed_with_tls_errors( + WebKitWebView *web_view, + char *failing_uri, + GTlsCertificate *certificate, + GTlsCertificateFlags errors, + gpointer user_data) + { + auto *webview = static_cast(user_data); + g_critical("on_load_failed_with_tls_errors: %s %p error= %d", failing_uri, webview, errors); + // TODO allow certificate for some certificate ? + // maybe we can use the pem from https://source.chromium.org/chromium/chromium/src/+/master:net/data/ssl/ev_roots/ + // webkit_web_context_allow_tls_certificate_for_host(webkit_web_view_get_context(web_view), certificate, uri->host); + // webkit_web_view_load_uri(web_view, failing_uri); + return false; + } -GtkWidget *on_create(WebKitWebView *web_view, - WebKitNavigationAction *navigation_action, - gpointer user_data) { - return GTK_WIDGET(web_view); -} + GtkWidget *on_create(WebKitWebView *web_view, + WebKitNavigationAction *navigation_action, + gpointer user_data) + { + return GTK_WIDGET(web_view); + } -void on_load_changed(WebKitWebView *web_view, - WebKitLoadEvent load_event, - gpointer user_data) { - auto *window = static_cast(user_data); - window->OnLoadChanged(load_event); -} + void on_load_changed(WebKitWebView *web_view, + WebKitLoadEvent load_event, + gpointer user_data) + { + auto *window = static_cast(user_data); + window->OnLoadChanged(load_event); + } -gboolean decide_policy_cb(WebKitWebView *web_view, - WebKitPolicyDecision *decision, - WebKitPolicyDecisionType type, - gpointer user_data) { - auto *window = static_cast(user_data); - return window->DecidePolicy(decision, type); -} + gboolean decide_policy_cb(WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType type, + gpointer user_data) + { + auto *window = static_cast(user_data); + return window->DecidePolicy(decision, type); + } } @@ -55,26 +60,29 @@ WebviewWindow::WebviewWindow( const std::string &title, int width, int height, - int title_bar_height -) : method_channel_(method_channel), - window_id_(window_id), - on_close_callback_(std::move(on_close_callback)), - default_user_agent_() { + int title_bar_height) : method_channel_(method_channel), + window_id_(window_id), + on_close_callback_(std::move(on_close_callback)), + default_user_agent_() +{ g_object_ref(method_channel_); window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(window_), "destroy", - G_CALLBACK(+[](GtkWidget *, gpointer arg) { - auto *window = static_cast(arg); - if (window->on_close_callback_) { - window->on_close_callback_(); - } - auto *args = fl_value_new_map(); - fl_value_set(args, fl_value_new_string("id"), fl_value_new_int(window->window_id_)); - fl_method_channel_invoke_method( - FL_METHOD_CHANNEL(window->method_channel_), "onWindowClose", args, - nullptr, nullptr, nullptr); - }), this); + G_CALLBACK(+[](GtkWidget *, gpointer arg) + { + auto *window = static_cast(arg); + if (window->on_close_callback_) + { + window->on_close_callback_(); + } + auto *args = fl_value_new_map(); + fl_value_set(args, fl_value_new_string("id"), fl_value_new_int(window->window_id_)); + fl_method_channel_invoke_method( + FL_METHOD_CHANNEL(window->method_channel_), "onWindowClose", args, + nullptr, nullptr, nullptr); + }), + this); gtk_window_set_title(GTK_WINDOW(window_), title.c_str()); gtk_window_set_default_size(GTK_WINDOW(window_), width, height); gtk_window_set_position(GTK_WINDOW(window_), GTK_WIN_POS_CENTER); @@ -119,21 +127,25 @@ WebviewWindow::WebviewWindow( // Disconnect all delete-event handlers first in flutter 3.10.1, which causes delete_event not working. // Issues from flutter/engine: https://github.com/flutter/engine/pull/40033 guint handler_id = g_signal_handler_find(window_, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, title_bar); - if (handler_id > 0) { + if (handler_id > 0) + { g_signal_handler_disconnect(window_, handler_id); } } -WebviewWindow::~WebviewWindow() { +WebviewWindow::~WebviewWindow() +{ g_object_unref(method_channel_); printf("~WebviewWindow\n"); } -void WebviewWindow::Navigate(const char *url) { +void WebviewWindow::Navigate(const char *url) +{ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview_), url); } -void WebviewWindow::RunJavaScriptWhenContentReady(const char *java_script) { +void WebviewWindow::RunJavaScriptWhenContentReady(const char *java_script) +{ auto *manager = webkit_web_view_get_user_content_manager(WEBKIT_WEB_VIEW(webview_)); webkit_user_content_manager_add_script( manager, @@ -144,16 +156,19 @@ void WebviewWindow::RunJavaScriptWhenContentReady(const char *java_script) { nullptr)); } -void WebviewWindow::SetApplicationNameForUserAgent(const std::string &app_name) { +void WebviewWindow::SetApplicationNameForUserAgent(const std::string &app_name) +{ auto *setting = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webview_)); webkit_settings_set_user_agent(setting, (default_user_agent_ + app_name).c_str()); } -void WebviewWindow::Close() { +void WebviewWindow::Close() +{ gtk_window_close(GTK_WINDOW(window_)); } -void WebviewWindow::OnLoadChanged(WebKitLoadEvent load_event) { +void WebviewWindow::OnLoadChanged(WebKitLoadEvent load_event) +{ // notify history changed event. { auto can_go_back = webkit_web_view_can_go_back(WEBKIT_WEB_VIEW(webview_)); @@ -168,47 +183,56 @@ void WebviewWindow::OnLoadChanged(WebKitLoadEvent load_event) { } // notify load start/finished event. - switch (load_event) { - case WEBKIT_LOAD_STARTED: { - auto *args = fl_value_new_map(); - fl_value_set(args, fl_value_new_string("id"), fl_value_new_int(window_id_)); - fl_method_channel_invoke_method( - FL_METHOD_CHANNEL(method_channel_), "onNavigationStarted", args, - nullptr, nullptr, nullptr); - break; - } - case WEBKIT_LOAD_FINISHED: { - auto *args = fl_value_new_map(); - fl_value_set(args, fl_value_new_string("id"), fl_value_new_int(window_id_)); - fl_method_channel_invoke_method( - FL_METHOD_CHANNEL(method_channel_), "onNavigationCompleted", args, - nullptr, nullptr, nullptr); - break; - } - default :break; + switch (load_event) + { + case WEBKIT_LOAD_STARTED: + { + auto *args = fl_value_new_map(); + fl_value_set(args, fl_value_new_string("id"), fl_value_new_int(window_id_)); + fl_method_channel_invoke_method( + FL_METHOD_CHANNEL(method_channel_), "onNavigationStarted", args, + nullptr, nullptr, nullptr); + break; + } + case WEBKIT_LOAD_FINISHED: + { + auto *args = fl_value_new_map(); + fl_value_set(args, fl_value_new_string("id"), fl_value_new_int(window_id_)); + fl_method_channel_invoke_method( + FL_METHOD_CHANNEL(method_channel_), "onNavigationCompleted", args, + nullptr, nullptr, nullptr); + break; + } + default: + break; } - } -void WebviewWindow::GoForward() { +void WebviewWindow::GoForward() +{ webkit_web_view_go_forward(WEBKIT_WEB_VIEW(webview_)); } -void WebviewWindow::GoBack() { +void WebviewWindow::GoBack() +{ webkit_web_view_go_back(WEBKIT_WEB_VIEW(webview_)); } -void WebviewWindow::Reload() { +void WebviewWindow::Reload() +{ webkit_web_view_reload(WEBKIT_WEB_VIEW(webview_)); } -void WebviewWindow::StopLoading() { +void WebviewWindow::StopLoading() +{ webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(webview_)); } -gboolean WebviewWindow::DecidePolicy(WebKitPolicyDecision *decision, WebKitPolicyDecisionType type) { - if (type == WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION) { - auto *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision); +gboolean WebviewWindow::DecidePolicy(WebKitPolicyDecision *decision, WebKitPolicyDecisionType type) +{ + if (type == WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION) + { + auto *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION(decision); auto *navigation_action = webkit_navigation_policy_decision_get_navigation_action(navigation_decision); auto *request = webkit_navigation_action_get_request(navigation_action); auto *uri = webkit_uri_request_get_uri(request); @@ -222,18 +246,42 @@ gboolean WebviewWindow::DecidePolicy(WebKitPolicyDecision *decision, WebKitPolic return false; } -void WebviewWindow::EvaluateJavaScript(const char *java_script, FlMethodCall *call) { +void WebviewWindow::EvaluateJavaScript(const char *java_script, FlMethodCall *call) +{ +#ifdef WEBKIT_OLD_USED + webkit_web_view_run_javascript( +#else webkit_web_view_evaluate_javascript( - WEBKIT_WEB_VIEW(webview_), java_script, -1, nullptr, nullptr, nullptr, - [](GObject *object, GAsyncResult *result, gpointer user_data) { +#endif + WEBKIT_WEB_VIEW(webview_), java_script, +#ifndef WEBKIT_OLD_USED + -1, nullptr, nullptr, +#endif + nullptr, + [](GObject *object, GAsyncResult *result, gpointer user_data) + { auto *call = static_cast(user_data); GError *error = nullptr; - auto *js_result = webkit_web_view_evaluate_javascript_finish(WEBKIT_WEB_VIEW(object), result, &error); - if (!js_result) { + auto *js_result = +#ifdef WEBKIT_OLD_USED + webkit_web_view_run_javascript_finish( +#else + webkit_web_view_evaluate_javascript_finish( +#endif + WEBKIT_WEB_VIEW(object), result, &error); + if (!js_result) + { fl_method_call_respond_error(call, "failed to evaluate javascript.", error->message, nullptr, nullptr); g_error_free(error); - } else { - auto *js_value = jsc_value_to_json(js_result, 0); + } + else + { + auto *js_value = jsc_value_to_json( +#ifdef WEBKIT_OLD_USED + webkit_javascript_result_get_js_value +#endif + (js_result), + 0); fl_method_call_respond_success(call, js_value ? fl_value_new_string(js_value) : nullptr, nullptr); } g_object_unref(call); diff --git a/packages/desktop_webview_window/pubspec.yaml b/packages/desktop_webview_window/pubspec.yaml index 114b9957..f066bb2f 100644 --- a/packages/desktop_webview_window/pubspec.yaml +++ b/packages/desktop_webview_window/pubspec.yaml @@ -1,6 +1,6 @@ name: desktop_webview_window description: Show a webview window on your flutter desktop application. -version: 0.2.3 +version: 0.2.4 homepage: https://github.com/MixinNetwork/flutter-plugins/tree/main/packages/desktop_webview_window environment: