texinfo-commits
[Top][All Lists]
Advanced

[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;
+}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]