~aperezdc/kiln

a4c7b57f72238fc2b236ea293e572f1385ff322f — Adrian Perez de Castro 4 years ago f7a3ce5
gtkshell: Add simple GTK browser for testing purposes

Add the gtkshell/ subdirectory, which will be built if WebKitGTK is in
use and the "gtk_shell" feature is enabled, which will compile "kn-gtk",
a simple browser that can be used to test the Kiln WebKit extension.
4 files changed, 151 insertions(+), 0 deletions(-)

A gtkshell/main.c
A gtkshell/meson.build
M meson.build
M meson_options.txt
A gtkshell/main.c => gtkshell/main.c +134 -0
@@ 0,0 1,134 @@
/*
 * main.c
 * Copyright (C) 2020 Adrian Perez de Castro <aperez@igalia.com>
 *
 * Distributed under terms of the MIT license.
 */

#include <webkit2/webkit2.h>

static char *s_option_extensions_path = NULL;
static char *s_option_uri = NULL;

static gboolean
on_remaining_cli_option (const char *option_name G_GNUC_UNUSED,
                         const char *option_value,
                         void       *data G_GNUC_UNUSED,
                         GError    **error)
{
    g_autoptr(SoupURI) uri = soup_uri_new (option_value);
    if (!uri) {
        g_set_error_literal (error,
                             G_OPTION_ERROR,
                             G_OPTION_ERROR_FAILED,
                             "Invalid URI");
        return FALSE;
    }

    g_clear_pointer (&s_option_uri, g_free);
    s_option_uri = soup_uri_to_string (uri, FALSE);

    return TRUE;
}

static const GOptionEntry s_cli_options[] = {
    {
        "extensions-path", 'e', G_OPTION_FLAG_IN_MAIN,
        G_OPTION_ARG_FILENAME, &s_option_extensions_path,
        "Path to directory containing WebExtensions", "PATH"
    },
    {
        G_OPTION_REMAINING, '\0', G_OPTION_FLAG_NONE,
        G_OPTION_ARG_CALLBACK, on_remaining_cli_option,
    },
    {
        NULL,
    }
};

static GtkWidget*
create_web_view (void)
{
    g_autoptr(WebKitWebContext) context = webkit_web_context_new ();
    webkit_web_context_set_additional_plugins_directory (context, "/usr/lib/mozilla/plugins");

    if (s_option_extensions_path) {
        g_message ("WebExtensions path: %s", s_option_extensions_path);
        webkit_web_context_set_web_extensions_directory (context, s_option_extensions_path);
    } else {
        g_warning ("WebExtensions path has not been set - none will be loaded!");
    }

    g_autoptr(GtkWidget) web_view = webkit_web_view_new_with_context (context);

    /* Set those for convenience. */
    WebKitSettings *settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (web_view));
    webkit_settings_set_enable_plugins (settings, TRUE);
    webkit_settings_set_enable_write_console_messages_to_stdout (settings, TRUE);
    webkit_settings_set_enable_developer_extras (settings, TRUE);

    webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), s_option_uri ? : "https://ddg.gg");
    return g_steal_pointer (&web_view);
}

static void
on_web_view_properties_notify (WebKitWebView *web_view,
                               GParamSpec    *pspec G_GNUC_UNUSED,
                               GtkWindow     *window)
{
    const double progress = webkit_web_view_get_estimated_load_progress (web_view);
    const char *title = webkit_web_view_get_title (web_view);

    g_autofree char *new_title = g_strdup_printf ("Kiln - %s (%.0f%%)",
                                                  title ? : "(untitled)",
                                                  progress * 100.0);
    gtk_window_set_title (window, new_title);
}

static void
on_app_action_quit (GSimpleAction *action G_GNUC_UNUSED,
                    GVariant      *param G_GNUC_UNUSED,
                    void          *user_data)
{
    g_application_quit (G_APPLICATION (user_data));
}

static void
on_app_startup (GtkApplication *app)
{
    static const GActionEntry app_actions[] = {
        { .name = "quit", .activate = on_app_action_quit },
    };
    g_action_map_add_action_entries (G_ACTION_MAP (app), app_actions,
                                     G_N_ELEMENTS (app_actions), app);
    gtk_window_set_default_icon_name ("internet-browser");
}

static void
on_app_activate (GtkApplication *app)
{
    GtkWidget *window = gtk_application_window_new (app);
    gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (window), FALSE);
    gtk_window_set_title (GTK_WINDOW (window), "Kiln");

    GtkWidget *web_view = create_web_view ();
    gtk_container_add (GTK_CONTAINER (window), web_view);
    gtk_widget_show_all (window);

    g_signal_connect (web_view, "notify::estimated-load-progress",
                      G_CALLBACK (on_web_view_properties_notify), window);
    g_signal_connect (web_view, "notify::title",
                      G_CALLBACK (on_web_view_properties_notify), window);
}

int
main (int argc, char *argv[])
{
    g_autoptr(GtkApplication) app = gtk_application_new (NULL, G_APPLICATION_FLAGS_NONE);
    g_application_add_main_option_entries (G_APPLICATION (app), s_cli_options);
    g_autoptr(GOptionGroup) jsc_options = jsc_options_get_option_group ();
    g_application_add_option_group (G_APPLICATION (app), jsc_options);
    g_signal_connect (app, "activate", G_CALLBACK (on_app_activate), NULL);
    g_signal_connect (app, "startup", G_CALLBACK (on_app_startup), NULL);
    return g_application_run (G_APPLICATION (app), argc, argv);
}

A gtkshell/meson.build => gtkshell/meson.build +10 -0
@@ 0,0 1,10 @@
gtkshell_exe = executable('kn-gtk',
	'main.c',
	c_args: [
		'-DG_LOG_DOMAIN="Kiln-GtkShell"',
	],
	dependencies: [
		webkitgtk_dep,
		libkn_dep,
	],
)

M meson.build => meson.build +3 -0
@@ 15,9 15,11 @@ opt_build_jsc_shell = get_option('jsc_shell')
if opt_webkit_port == 'gtk'
	webkit_extension_dep_name = 'webkit2gtk-web-extension-4.0'
	javascriptcore_dep_name = 'javascriptcoregtk-4.0'
	webkitgtk_dep = dependency('webkit2gtk-4.0', required: get_option('gtk_shell'))
elif opt_webkit_port == 'wpe'
	webkit_extension_dep_name = 'wpe-web-extension-1.0'
	javascriptcore_dep_name = 'wpe-webkit-1.0'
	webkitgtk_dep = disabler()
endif

webkit_extension_dep = dependency(webkit_extension_dep_name,


@@ 34,6 36,7 @@ subdir('libkn')
subdir('modules')
subdir('wkext', if_found: webkit_extension_dep)
subdir('shell', if_found: javascriptcore_dep)
subdir('gtkshell', if_found: webkitgtk_dep)

documentation_option = get_option('documentation')
hotdoc_has_c_extension = false

M meson_options.txt => meson_options.txt +4 -0
@@ 11,6 11,10 @@ option('jsc_shell',
	type: 'feature',
	description: 'Build JavaScriptCore CLI shell with module loader'
)
option('gtk_shell',
	type: 'feature',
	description: 'Build example WebKitGTK shell'
)
option('documentation',
	type: 'feature',
	value: 'auto',