Skip to content

Commit

Permalink
[FEAT] Add Backwards compatibility to webkit2gtk-4.0 (#311)
Browse files Browse the repository at this point in the history
* feat: add fix for webkit2gtk 4.0 linux

* Revert "fix linux webkit2gtk deprecated error (#246)"

This reverts commit 0eeeb80.

* 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
  • Loading branch information
prateekmedia committed Jan 31, 2024
1 parent 40bf8cf commit 1134cc0
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 93 deletions.
4 changes: 4 additions & 0 deletions 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.
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop_webview_window/README.md
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion packages/desktop_webview_window/linux/CMakeLists.txt
Expand Up @@ -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"
Expand Down
228 changes: 138 additions & 90 deletions packages/desktop_webview_window/linux/webview_window.cc
Expand Up @@ -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<WebviewWindow *>(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<WebviewWindow *>(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<WebviewWindow *>(user_data);
window->OnLoadChanged(load_event);
}
void on_load_changed(WebKitWebView *web_view,
WebKitLoadEvent load_event,
gpointer user_data)
{
auto *window = static_cast<WebviewWindow *>(user_data);
window->OnLoadChanged(load_event);
}

gboolean decide_policy_cb(WebKitWebView *web_view,
WebKitPolicyDecision *decision,
WebKitPolicyDecisionType type,
gpointer user_data) {
auto *window = static_cast<WebviewWindow *>(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<WebviewWindow *>(user_data);
return window->DecidePolicy(decision, type);
}

}

Expand All @@ -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<WebviewWindow *>(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<WebviewWindow *>(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);
Expand Down Expand Up @@ -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,
Expand All @@ -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_));
Expand All @@ -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);
Expand All @@ -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<FlMethodCall *>(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);
Expand Down
2 changes: 1 addition & 1 deletion 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:
Expand Down

0 comments on commit 1134cc0

Please sign in to comment.