Skip to content

Commit

Permalink
Refactor web extension for GTK4. Solve deprecations.
Browse files Browse the repository at this point in the history
We now have a generic EvalJS method that allows running arbitrary JS
this means we do not have to build specific callbacks. The JS code can
just be inlined from where it is called.
  • Loading branch information
lwindolf committed Jun 20, 2024
1 parent dea9940 commit b0b1d89
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 83 deletions.
30 changes: 16 additions & 14 deletions src/ui/liferea_browser.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,31 +406,33 @@ liferea_browser_location_changed (LifereaBrowser *browser, const gchar *location
static void
liferea_browser_load_finished_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
WebKitJavascriptResult *js_result;
JSCValue *value;
GError *error = NULL;
JSCValue *value;
GError *error = NULL;

js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (object), result, &error);
if (!js_result) {
value = webkit_web_view_evaluate_javascript_finish (WEBKIT_WEB_VIEW (object), result, &error);
if (!value) {
debug (DEBUG_HTML, "Error running javascript: %s", error->message);
g_error_free (error);
return;
}

value = webkit_javascript_result_get_js_value (js_result);
if (jsc_value_is_boolean (value)) {
LifereaBrowser *browser = LIFEREA_BROWSER (user_data);
gboolean result = jsc_value_to_boolean (value);

if (!result && browser->readerMode && browser->url) {
debug (DEBUG_HTML, "loadContent() reader mode fail -> reloading without reader");
browser->readerMode = FALSE;
liferea_browser_launch_URL_internal (browser, browser->url);
JSCException *exception = jsc_context_get_exception (jsc_value_get_context (value));
if (exception) {
g_warning ("Error running javascript: %s", jsc_exception_get_message (exception));
} else {
LifereaBrowser *browser = LIFEREA_BROWSER (user_data);
gboolean result = jsc_value_to_boolean (value);
if (result && browser->readerMode && browser->url) {
debug (DEBUG_HTML, "loadContent() reader mode fail -> reloading without reader");
browser->readerMode = FALSE;
liferea_browser_launch_URL_internal (browser, browser->url);
}
}
} else {
g_warning ("Error running javascript: unexpected return value");
}
webkit_javascript_result_unref (js_result);
g_object_unref (value);
}

void
Expand Down
40 changes: 27 additions & 13 deletions src/webkit/liferea_web_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ liferea_web_view_load_status_changed (WebKitWebView *view, WebKitLoadEvent event
isFullscreen = GPOINTER_TO_INT(g_object_steal_data(
G_OBJECT(view), "fullscreen_on"));
if (isFullscreen == TRUE) {
webkit_web_view_run_javascript (view, "document.webkitExitFullscreen();", NULL, NULL, NULL);
webkit_web_view_evaluate_javascript (view, "document.webkitExitFullscreen();", -1, NULL, NULL, NULL, NULL, NULL);
}
break;
}
Expand Down Expand Up @@ -695,11 +695,11 @@ liferea_web_view_init(LifereaWebView *self)
}

static void
scroll_pagedown_callback (GObject *source_object, GAsyncResult *res, gpointer user_data)
liferea_web_view_scroll_pagedown_callback (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
GVariant *result = NULL;
GError *error = NULL;
gboolean scrolled;
gchar *output = NULL;

result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error);

Expand All @@ -709,31 +709,45 @@ scroll_pagedown_callback (GObject *source_object, GAsyncResult *res, gpointer us
return;
}

g_variant_get (result, "(b)", &scrolled);
g_variant_get (result, "(s)", &output);

if (!scrolled) {
if (g_str_equal(output, "false"))
on_next_unread_item_activate (NULL, NULL, NULL);
}

g_free (output);
}

void
liferea_web_view_scroll_pagedown (LifereaWebView *self)
{
if (!self->dbus_connection) return;

gchar *cmd = "\
window.scrollTo({top: window.pageYOffset + window.innerHeight, behavior: 'smooth'}); \
doc = document.documentElement; \
console.log(window.pageYOffset); \
console.log(doc.scrollHeight - (doc.scrollTop + doc.clientHeight) > 0); \
doc.scrollHeight - (doc.scrollTop + doc.clientHeight) > 0; \
";

if (!self->dbus_connection)
return;

g_dbus_connection_call (self->dbus_connection,
LIFEREA_WEB_EXTENSION_BUS_NAME,
LIFEREA_WEB_EXTENSION_OBJECT_PATH,
LIFEREA_WEB_EXTENSION_INTERFACE_NAME,
"ScrollPageDown",
g_variant_new ("(t)", webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (self))),
((const GVariantType *) "(b)"),
"EvalJs",
g_variant_new (
"(ts)",
webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (self)),
cmd
),
((const GVariantType *) "(s)"),
G_DBUS_CALL_FLAGS_NONE,
-1, /* Default timeout */
NULL,
scroll_pagedown_callback,
NULL);
liferea_web_view_scroll_pagedown_callback,
NULL
);
}

void
Expand Down
102 changes: 51 additions & 51 deletions src/webkit/web_extension/liferea_web_extension.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/**
* @file liferea_web_extension.c Control WebKit2 via DBUS from Liferea
*
* Copyright (C) 2016 Leiaz <[email protected]>
* Copyright (C) 2016 Leiaz <[email protected]>
* Copyright (C) 2024 Lars Windolf <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -19,8 +20,7 @@
*/

#include <webkit2/webkit-web-extension.h>
#define WEBKIT_DOM_USE_UNSTABLE_API
#include <webkitdom/WebKitDOMDOMWindowUnstable.h>
#include <JavaScriptCore/JavaScript.h>

#include "liferea_web_extension.h"
#include "liferea_web_extension_names.h"
Expand All @@ -45,9 +45,14 @@ G_DEFINE_TYPE (LifereaWebExtension, liferea_web_extension, G_TYPE_OBJECT)
static const char introspection_xml[] =
"<node>"
" <interface name='net.sf.liferea.WebExtension'>"
" <method name='ScrollPageDown'>"
" <method name='EvalJs'>"
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='b' name='scrolled' direction='out'/>"
" <arg type='s' name='js' direction='in'/>"
" <arg type='s' name='result' direction='out'/>"
" </method>"
" <method name='EvalJsNoResult'>"
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='s' name='js' direction='in'/>"
" </method>"
" <signal name='PageCreated'>"
" <arg type='t' name='page_id' direction='out'/>"
Expand Down Expand Up @@ -82,39 +87,6 @@ liferea_web_extension_init (LifereaWebExtension *self)
self->liferea_settings = g_settings_new ("net.sf.liferea");
}

static WebKitDOMDOMWindow*
liferea_web_extension_get_dom_window (LifereaWebExtension *self, guint64 page_id)
{
WebKitWebPage *page;
WebKitDOMDocument *document;
WebKitDOMDOMWindow *window;

page = webkit_web_extension_get_page (self->webkit_extension, page_id);
document = webkit_web_page_get_dom_document (page);
window = webkit_dom_document_get_default_view (document);

return window;
}

/*
* \returns TRUE if scrolling happened, FALSE if the end was reached
*/
static gboolean
liferea_web_extension_scroll_page_down (LifereaWebExtension *self, guint64 page_id)
{
glong old_scroll_y, new_scroll_y, increment;
WebKitDOMDOMWindow *window;

window = liferea_web_extension_get_dom_window (self, page_id);

old_scroll_y = webkit_dom_dom_window_get_scroll_y (window);
increment = webkit_dom_dom_window_get_inner_height (window);
webkit_dom_dom_window_scroll_by (window, 0, increment);
new_scroll_y = webkit_dom_dom_window_get_scroll_y (window);

return (new_scroll_y > old_scroll_y);
}

static gboolean
on_authorize_authenticated_peer (GDBusAuthObserver *observer,
GIOStream *stream,
Expand Down Expand Up @@ -153,13 +125,41 @@ handle_dbus_method_call (GDBusConnection *connection,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
if (g_strcmp0 (method_name, "ScrollPageDown") == 0) {
guint64 page_id;
gboolean scrolled;

g_variant_get (parameters, "(t)", &page_id);
scrolled = liferea_web_extension_scroll_page_down (LIFEREA_WEB_EXTENSION (user_data), page_id);
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", scrolled));
guint64 page_id;
WebKitWebPage *page;

// We only implement a generic callbacks 'EvalJs' and 'EvalJsNoResult' which should
// be used to run all everything we might need through Javascript...

// EvalJs handling inspired by https://github.com/fanglingsu/vimb
if (g_strcmp0 (method_name, "EvalJs") == 0) {
gchar *script;
JSCValue *result = NULL;
JSCContext *jsContext;

g_variant_get(parameters, "(ts)", &page_id, &script);

page = webkit_web_extension_get_page(LIFEREA_WEB_EXTENSION (user_data)->webkit_extension, page_id);
if (!page) {
g_warning ("invalid page id %lu", page_id);
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS, "Invalid page ID: %"G_GUINT64_FORMAT, page_id);
return;
}

jsContext = webkit_frame_get_js_context_for_script_world (
webkit_web_page_get_main_frame (page),
webkit_script_world_get_default ()
);

result = jsc_context_evaluate (jsContext, script, -1);
if (!g_strcmp0 (method_name, "EvalJsNoResult")) {
g_dbus_method_invocation_return_value(invocation, NULL);
} else {
g_autofree gchar *str = jsc_value_to_string (result);
g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", str));
}
g_object_unref (result);
}
}

Expand Down Expand Up @@ -215,15 +215,15 @@ on_send_request (WebKitWebPage *web_page,
gpointer web_extension)
{
SoupMessageHeaders *headers = webkit_uri_request_get_http_headers (request);
gboolean do_not_track;

do_not_track = g_settings_get_boolean (
LIFEREA_WEB_EXTENSION (web_extension)->liferea_settings,
"do-not-track");
if (!headers)
return FALSE;

if (do_not_track && headers) {
if (g_settings_get_boolean (LIFEREA_WEB_EXTENSION (web_extension)->liferea_settings, "do-not-track"))
soup_message_headers_append (headers, "DNT", "1");
}

if (g_settings_get_boolean (LIFEREA_WEB_EXTENSION (web_extension)->liferea_settings, "do-not-sell"))
soup_message_headers_append (headers, "Sec-GPC", "1");

return FALSE;
}
Expand Down
15 changes: 10 additions & 5 deletions src/webkit/webkit.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,11 +460,16 @@ liferea_webkit_run_js (GtkWidget *widget, gchar *js, GAsyncReadyCallback cb)
// No matter what was before we need JS now
g_object_set (webkit_web_view_get_settings (WEBKIT_WEB_VIEW (widget)), "enable-javascript", TRUE, NULL);

webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (widget),
js,
NULL,
cb,
g_object_get_data (G_OBJECT (widget), "htmlview"));
webkit_web_view_evaluate_javascript (
WEBKIT_WEB_VIEW (widget),
js,
-1,
NULL,
NULL,
NULL,
cb,
g_object_get_data (G_OBJECT (widget), "htmlview")
);
g_free (js);
}

Expand Down

0 comments on commit b0b1d89

Please sign in to comment.