[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[no subject]
From: |
Gavin D. Smith |
Date: |
Sun, 20 Mar 2022 04:54:54 -0400 (EDT) |
branch: master
commit 33ed9ca471dec176fbda13e78e35e340fe5beacf
Author: Gavin Smith <gavinsmith0123@gmail.com>
AuthorDate: Sun May 5 14:19:49 2019 +0100
Commit a start of creating a help browser with WebKitGTK.
---
js/wkinfo/Makefile.am | 17 ++++
js/wkinfo/configure.ac | 5 +
js/wkinfo/extension.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++++
js/wkinfo/main.c | 176 ++++++++++++++++++++++++++++++++++++
4 files changed, 439 insertions(+)
diff --git a/js/wkinfo/Makefile.am b/js/wkinfo/Makefile.am
new file mode 100644
index 0000000000..8bccc6d715
--- /dev/null
+++ b/js/wkinfo/Makefile.am
@@ -0,0 +1,17 @@
+AUTOMAKE_OPTIONS=foreign
+ACLOCAL_AMFLAGS = -I m4
+
+webextension_LTLIBRARIES = libmyappwebextension.la
+webextensiondir = $(libdir)/MyApp/web-extension
+libmyappwebextension_la_SOURCES = extension.c
+libmyappwebextension_la_CFLAGS = $(AM_CFLAGS) $(WEB_EXTENSION_CFLAGS)
+libmyappwebextension_la_LIBADD = $(WEB_EXTENSION_LIBS)
+libmyappwebextension_la_LDFLAGS = -module -avoid-version -no-undefined
+
+bin_PROGRAMS=webkit
+
+webkit_SOURCES=main.c
+
+AM_CFLAGS=`pkg-config --cflags gtk+-3.0 webkit2gtk-3.0`
+
+AM_LDFLAGS=`pkg-config --libs gtk+-3.0 webkit2gtk-3.0`
diff --git a/js/wkinfo/configure.ac b/js/wkinfo/configure.ac
new file mode 100644
index 0000000000..ea09f879de
--- /dev/null
+++ b/js/wkinfo/configure.ac
@@ -0,0 +1,5 @@
+AC_INIT([gnudoc], [0])
+AC_CONFIG_MACRO_DIRS([m4])
+AM_INIT_AUTOMAKE
+LT_INIT
+AC_OUTPUT([Makefile])
diff --git a/js/wkinfo/extension.c b/js/wkinfo/extension.c
new file mode 100644
index 0000000000..d39bea5ed8
--- /dev/null
+++ b/js/wkinfo/extension.c
@@ -0,0 +1,241 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <gtk/gtk.h>
+#include <webkit2/webkit-web-extension.h>
+
+/* Data retrieved from document */
+static char *next_link;
+
+/* For communicating with the main Gtk process */
+static struct sockaddr_un main_name;
+static size_t main_name_size;
+
+/* Name of the socket that we create in this process to send to the socket
+ of the main process. */
+static char *our_socket_file;
+static int socket_id;
+
+static void
+remove_our_socket (void)
+{
+ if (our_socket_file)
+ unlink (our_socket_file);
+}
+
+gboolean
+request_callback (WebKitWebPage *web_page,
+ WebKitURIRequest *request,
+ WebKitURIResponse *redirected_response,
+ gpointer user_data)
+{
+ const char *uri = webkit_uri_request_get_uri (request);
+
+ g_print ("Intercepting link <%s>\n", uri);
+
+ if (!strcmp (uri, "internal:next"))
+ {
+ if (next_link)
+ {
+ g_print ("redirect to |%s|\n", next_link);
+
+ webkit_uri_request_set_uri (request, next_link);
+ /* This doesn't work as webkit_web_page_get_uri still
+ returns "internal:next". */
+ }
+ }
+ return false;
+}
+
+void
+document_loaded_callback (WebKitWebPage *web_page,
+ gpointer user_data)
+{
+ g_print ("Page %d loaded for %s\n",
+ webkit_web_page_get_id (web_page),
+ webkit_web_page_get_uri (web_page));
+
+ WebKitDOMDocument *dom_document
+ = webkit_web_page_get_dom_document (web_page);
+
+ if (!dom_document)
+ {
+ g_print ("No DOM document\n");
+ return;
+ }
+
+ WebKitDOMHTMLCollection *links =
+ webkit_dom_document_get_links (dom_document);
+
+ if (!links)
+ {
+ g_print ("No links\n");
+ return;
+ }
+
+ gulong num_links = webkit_dom_html_collection_get_length (links);
+ g_print ("Found %d links\n",
+ webkit_dom_html_collection_get_length (links));
+
+ gulong i;
+ for (i = 0; i < num_links; i++)
+ {
+ WebKitDOMNode *node
+ = webkit_dom_html_collection_item (links, i);
+ if (!node)
+ {
+ g_print ("No node\n");
+ return;
+ }
+
+ WebKitDOMElement *element;
+ if (WEBKIT_DOM_IS_ELEMENT(node))
+ {
+ element = WEBKIT_DOM_ELEMENT(node);
+ }
+ else
+ {
+ /* When would this happen? */
+ g_print ("Not an DOM element\n");
+ continue;
+ }
+
+ gchar *rel = 0, *href = 0;
+
+ rel = webkit_dom_element_get_attribute (element, "rel");
+ if (rel && *rel)
+ {
+ href = webkit_dom_element_get_attribute (element, "href");
+ }
+ if (rel && href)
+ {
+ g_print ("rel:href is |%s:%s|\n", rel, href);
+ if (!strcmp (rel, "next"))
+ {
+ free (next_link); next_link = 0;
+
+ const char *current_uri = webkit_web_page_get_uri (web_page);
+ if (current_uri)
+ {
+ const char *p = current_uri;
+ const char *q;
+
+ g_print ("current uri is |%s|\n", current_uri);
+ while ((q = strchr (p, '/')))
+ {
+ q++;
+ p = q;
+ }
+ if (p != current_uri)
+ {
+ next_link = malloc ((p - current_uri)
+ + strlen (href) + 1);
+ memcpy (next_link, current_uri, p - current_uri);
+ strcpy (next_link + (p - current_uri), href);
+ g_print ("saved ref |%s|\n", next_link);
+
+ /*
+ sendto (socket_id, next_link, strlen (next_link), 0,
+ (struct sockaddr *) &main_name, main_name_size);
+ */
+ }
+ }
+ }
+ }
+ g_free (rel); g_free (href);
+ }
+}
+
+
+
+static void
+web_page_created_callback (WebKitWebExtension *extension,
+ WebKitWebPage *web_page,
+ gpointer user_data)
+{
+ g_print ("Page %d created for %s\n",
+ webkit_web_page_get_id (web_page),
+ webkit_web_page_get_uri (web_page));
+
+ g_signal_connect (web_page, "document-loaded",
+ G_CALLBACK (document_loaded_callback),
+ NULL);
+
+ g_signal_connect_object (web_page, "send-request",
+ G_CALLBACK (request_callback),
+ NULL, 0);
+}
+
+static int
+make_named_socket (const char *filename)
+{
+ struct sockaddr_un name;
+ size_t size;
+
+ /* Create the socket. */
+ socket_id = socket (PF_LOCAL, SOCK_DGRAM, 0);
+ if (socket_id < 0)
+ {
+ perror ("socket (web process)");
+ exit (EXIT_FAILURE);
+ }
+
+ /* Bind a name to the socket. */
+ name.sun_family = AF_LOCAL;
+ strncpy (name.sun_path, filename, sizeof (name.sun_path));
+ name.sun_path[sizeof (name.sun_path) - 1] = '\0';
+
+ /* The size of the address is
+ the offset of the start of the filename,
+ plus its length (not including the terminating null byte).
+ Alternatively you can just do:
+ size = SUN_LEN (&name);
+ */
+ size = (offsetof (struct sockaddr_un, sun_path)
+ + strlen (name.sun_path));
+
+ if (bind (socket_id, (struct sockaddr *) &name, size) < 0)
+ {
+ perror ("bind (web process)");
+ exit (EXIT_FAILURE);
+ }
+ /* Do we really need to bind the socket if we are not receiving messages? */
+
+ atexit (&remove_our_socket);
+}
+
+void
+initialize_socket (const char *main_socket_file)
+{
+ if (!our_socket_file)
+ {
+ our_socket_file = tmpnam (0);
+ socket_id = make_named_socket (our_socket_file);
+ }
+ else
+ g_print ("bug: web process initialized twice\n");
+
+ /* Set the address of the socket in the main Gtk process. */
+ main_name.sun_family = AF_LOCAL;
+ strcpy (main_name.sun_path, main_socket_file);
+ main_name_size = strlen (main_name.sun_path) + sizeof (main_name.sun_family);
+}
+
+G_MODULE_EXPORT void
+webkit_web_extension_initialize_with_user_data (WebKitWebExtension *extension,
+ GVariant *user_data)
+{
+ const char *socket_file = g_variant_get_bytestring (user_data);
+ g_print ("thread id %s\n", socket_file);
+
+ initialize_socket (socket_file);
+
+ g_signal_connect (extension, "page-created",
+ G_CALLBACK (web_page_created_callback),
+ NULL);
+}
diff --git a/js/wkinfo/main.c b/js/wkinfo/main.c
new file mode 100644
index 0000000000..f5e6dabf62
--- /dev/null
+++ b/js/wkinfo/main.c
@@ -0,0 +1,176 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+static void destroyWindowCb(GtkWidget* widget, GtkWidget* window);
+static gboolean closeWebViewCb(WebKitWebView* webView, GtkWidget* window);
+static gboolean onkeypress(GtkWidget *webView,
+ GdkEvent *event,
+ gpointer user_data);
+
+#define WEB_EXTENSIONS_DIRECTORY "/home/g/src/texinfo/GIT/js/wkinfo/.libs"
+
+static char *socket_file;
+int socket_id;
+
+static void
+remove_socket (void)
+{
+ if (socket_file)
+ unlink (socket_file);
+}
+
+static int
+make_named_socket (const char *filename)
+{
+ struct sockaddr_un name;
+ int sock;
+ size_t size;
+
+ /* Create the socket. */
+ sock = socket (PF_LOCAL, SOCK_DGRAM, 0);
+ if (sock < 0)
+ {
+ perror ("socket");
+ exit (EXIT_FAILURE);
+ }
+
+ /* Bind a name to the socket. */
+ name.sun_family = AF_LOCAL;
+ strncpy (name.sun_path, filename, sizeof (name.sun_path));
+ name.sun_path[sizeof (name.sun_path) - 1] = '\0';
+
+ /* The size of the address is
+ the offset of the start of the filename,
+ plus its length (not including the terminating null byte).
+ Alternatively you can just do:
+ size = SUN_LEN (&name);
+ */
+ size = (offsetof (struct sockaddr_un, sun_path)
+ + strlen (name.sun_path));
+
+ if (bind (sock, (struct sockaddr *) &name, size) < 0)
+ {
+ perror ("bind");
+ exit (EXIT_FAILURE);
+ }
+
+ atexit (&remove_socket);
+
+ return sock;
+}
+
+static void
+initialize_web_extensions (WebKitWebContext *context,
+ gpointer user_data)
+{
+ /* Web Extensions get a different ID for each Web Process */
+ static guint32 unique_id = 0;
+
+ /* Make a Unix domain socket for communication with the browser process.
+ Some example code and documentation for WebKitGTK uses dbus instead. */
+
+ if (!socket_file)
+ {
+ socket_file = tmpnam (0);
+ socket_id = make_named_socket (socket_file);
+ }
+ else
+ g_print ("bug: more than one web process started\n");
+
+ webkit_web_context_set_web_extensions_directory (
+ context, WEB_EXTENSIONS_DIRECTORY);
+ webkit_web_context_set_web_extensions_initialization_user_data (
+ context, g_variant_new_bytestring (socket_file));
+}
+
+
+int main(int argc, char* argv[])
+{
+ // Initialize GTK+
+ gtk_init(&argc, &argv);
+
+ // Create an 800x600 window that will contain the browser instance
+ GtkWidget *main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size(GTK_WINDOW(main_window), 800, 600);
+
+ /* Load "extensions". The web browser is run in a separate process
+ and we can only access the DOM in that process. */
+ g_signal_connect (webkit_web_context_get_default (),
+ "initialize-web-extensions",
+ G_CALLBACK (initialize_web_extensions),
+ NULL);
+
+ // Create a browser instance
+ WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
+
+ /* Disable JavaScript */
+ WebKitSettings *settings = webkit_web_view_group_get_settings
(webkit_web_view_get_group (webView));
+ webkit_settings_set_enable_javascript (settings, FALSE);
+
+
+ // Put the browser area into the main window
+ gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(webView));
+
+ // Set up callbacks so that if either the main window or the browser
+ // instance is closed, the program will exit.
+ g_signal_connect(main_window, "destroy", G_CALLBACK(destroyWindowCb),
NULL);
+ g_signal_connect(webView, "close", G_CALLBACK(closeWebViewCb),
main_window);
+
+ g_signal_connect(webView, "key_press_event", G_CALLBACK(onkeypress),
main_window);
+
+ // Load a web page into the browser instance
+ //webkit_web_view_load_uri(webView, "http://www.webkitgtk.org/");
+ webkit_web_view_load_uri(webView,
"file:/home/g/src/texinfo/GIT/js/test/hello/index.html");
+
+ // Make sure that when the browser area becomes visible, it will get mouse
+ // and keyboard events
+ gtk_widget_grab_focus(GTK_WIDGET(webView));
+
+ // Make sure the main window and all its contents are visible
+ gtk_widget_show_all(main_window);
+
+ // Run the main GTK+ event loop
+ gtk_main();
+
+ return 0;
+}
+
+static gboolean onkeypress(GtkWidget *webView,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ GdkEventKey *k = (GdkEventKey *) event;
+
+ switch (k->keyval)
+ {
+ case GDK_KEY_q:
+ gtk_main_quit();
+ break;
+ case GDK_KEY_n:
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webView), "internal:next");
+ break;
+ default:
+ ;
+ }
+
+}
+
+
+static void destroyWindowCb(GtkWidget* widget, GtkWidget* window)
+{
+ gtk_main_quit();
+}
+
+static gboolean closeWebViewCb(WebKitWebView* webView, GtkWidget* window)
+{
+ gtk_widget_destroy(window);
+ return TRUE;
+}
- master updated (cd0de30b76 -> ca0de032c7), Gavin D. Smith, 2022/03/20
- [no subject],
Gavin D. Smith <=
- [no subject], Gavin D. Smith, 2022/03/20
- [no subject], Gavin D. Smith, 2022/03/20
- [no subject], Gavin D. Smith, 2022/03/20
- [no subject], Gavin D. Smith, 2022/03/20
- [no subject], Gavin D. Smith, 2022/03/20
- [no subject], Gavin D. Smith, 2022/03/20
- [no subject], Gavin D. Smith, 2022/03/20
- [no subject], Gavin D. Smith, 2022/03/20
- [no subject], Gavin D. Smith, 2022/03/20
- [no subject], Gavin D. Smith, 2022/03/20