logo

badwolf

Minimalist and privacy-oriented WebKitGTK+ browser
commit: d57b655fecccbdee1f745e74a4578c14aeef5bcb
parent: b6e995810f9cba4dac83d57643a5f9698699cbad
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Wed, 26 Aug 2020 15:10:51 +0200

Merge branch 'features/suggestions' into develop

Diffstat:

MKnowledgeBase.md17+++++++++++++++++
MMakefile6+++---
MREADME.md1+
Mbadwolf.18++++++++
Mbadwolf.c17+++++++++++++++++
Abookmarks.c117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abookmarks.h3+++
Mconfig.h3+++
8 files changed, 169 insertions(+), 3 deletions(-)

diff --git a/KnowledgeBase.md b/KnowledgeBase.md @@ -2,3 +2,20 @@ - WebKit2 Extensions Tutorial: https://blogs.igalia.com/carlosgc/2013/09/10/webkit2gtk-web-process-extensions/ - https://trac.torproject.org/projects/tor/wiki/doc/ImportantGoogleChromeBugs / https://trac.torproject.org/projects/tor/ticket/1925 - https://webkit.org/blog/3476/content-blockers-first-look/ + +# Bookmark formats +The different plain-text formats used by web browsers found in the wild, done +in Augmented Backus–Naur Form (ABNF). + +url = *CHAR +title = *CHAR + +## uzbl +bookmark = URL TAB title [TAB tags] +tags = *(*CHAR SP) + +Documenter comment: How does it manages when the separator (TAB here) is +present in the title? + +## qutebrowser +bookmark = URL SP title diff --git a/Makefile b/Makefile @@ -24,9 +24,9 @@ INKSCAPE ?= inkscape # for i in 24 32 48 64 128 256; do echo icons/hicolor/${i}x${i}/apps/badwolf.png; done | tr '\n' ' ' ICON_SIZES = icons/hicolor/24x24/apps/badwolf.png icons/hicolor/32x32/apps/badwolf.png icons/hicolor/48x48/apps/badwolf.png icons/hicolor/64x64/apps/badwolf.png icons/hicolor/128x128/apps/badwolf.png icons/hicolor/256x256/apps/badwolf.png -DEPS = gtk+-3.0 webkit2gtk-4.0 libsoup-2.4 -SRCS = uri.c uri_test.c keybindings.c downloads.c badwolf.c -OBJS = uri.o keybindings.o downloads.o badwolf.o +DEPS = gtk+-3.0 webkit2gtk-4.0 libsoup-2.4 libxml-2.0 +SRCS = bookmarks.c uri.c uri_test.c keybindings.c downloads.c badwolf.c +OBJS = bookmarks.o uri.o keybindings.o downloads.o badwolf.o OBJS_test = uri_test.o EXE = badwolf EXE_test = uri_test diff --git a/README.md b/README.md @@ -55,6 +55,7 @@ Dependencies are: - C11 Compiler (such as clang or gcc) - [WebKitGTK](https://webkitgtk.org/), only the latest stable is supported +- [libxml-2.0](http://www.xmlsoft.org/), no known version limitation - POSIX make with extension for shell in variables (works with GNU, {Net,Free,Open}BSD) - A pkg-config implementation (pkgconf is recommended) - (optionnal) gettext implementation (such as GNU Gettext) diff --git a/badwolf.1 b/badwolf.1 @@ -75,6 +75,14 @@ A more generic variable name is also intended to be used in the future. .El .Sh FILES .Bl -tag -width Ds -compact +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/bookmarks.xbel +XBEL (XML Bookmark Exchange Language) file, known to be currently supported by: +.Xr elinks 1 , +.Xr konqueror 1 , +.Xr kbookmarkeditor 1 . Doing a symbolic link from their path works fine. +.Pp +For more information about this format see: +.Lk http://pyxml.sourceforge.net/topics/xbel/ .It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/webkit-web-extensions/ Directory containing the .Lk https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebExtension.html WebKitWebExtensions diff --git a/badwolf.c b/badwolf.c @@ -6,6 +6,8 @@ #include "config.h" #include "downloads.h" +#include "bookmarks.h" +#include "config.h" #include "keybindings.h" #include "uri.h" @@ -21,6 +23,7 @@ const gchar *version = VERSION; static gchar *web_extensions_directory; static int context_id_counter = 0; +GtkTreeModel *bookmarks_completion_model; static gboolean WebViewCb_close(WebKitWebView *webView, gpointer user_data); static gboolean WebViewCb_web_process_terminated(WebKitWebView *webView, @@ -736,6 +739,15 @@ new_browser(struct Window *window, const gchar *target_url, struct Client *old_b gtk_label_set_single_line_mode(GTK_LABEL(browser->statuslabel), TRUE); gtk_label_set_ellipsize(GTK_LABEL(browser->statuslabel), BADWOLF_STATUSLABEL_ELLIPSIZE); + if(bookmarks_completion_model != NULL) + { + GtkEntryCompletion *location_completion = gtk_entry_completion_new(); + GtkTreeModel *location_completion_model = bookmarks_completion_model; + + bookmarks_completion_setup(location_completion, location_completion_model); + gtk_entry_set_completion(GTK_ENTRY(browser->location), location_completion); + } + gtk_entry_set_text(GTK_ENTRY(browser->location), target_url); gtk_entry_set_input_purpose(GTK_ENTRY(browser->location), GTK_INPUT_PURPOSE_URL); @@ -930,6 +942,9 @@ main(int argc, char *argv[]) g_build_filename(g_get_user_data_dir(), "badwolf", "webkit-web-extension", NULL); fprintf(stderr, _("webkit-web-extension directory set to: %s\n"), web_extensions_directory); + bookmarks_completion_model = bookmarks_completion_init(); + g_object_ref(bookmarks_completion_model); + window->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); window->notebook = gtk_notebook_new(); window->new_tab = gtk_button_new_from_icon_name("tab-new-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); @@ -997,6 +1012,8 @@ main(int argc, char *argv[]) gtk_main(); + g_object_unref(bookmarks_completion_model); + #if 0 /* TRANSLATOR Ignore this entry. Done for forcing Unicode in xgettext. */ _("ø"); diff --git a/bookmarks.c b/bookmarks.c @@ -0,0 +1,117 @@ +#include "bookmarks.h" + +#include "badwolf.h" +#include "config.h" + +#include <glib/gprintf.h> /* g_fprintf() */ +#include <gtk/gtk.h> +#include <libxml/xpath.h> +#include <unistd.h> /* access() */ + +static gboolean +location_completion_matches(GtkEntryCompletion *completion, + const gchar *key, + GtkTreeIter *iter, + gpointer user_data) +{ + (void)user_data; + gchar *buffer; + gchar *pattern; + gboolean result; + + pattern = g_strdup_printf("*%s*", key); + + gtk_tree_model_get(gtk_entry_completion_get_model(completion), iter, 0, &buffer, -1); + result = g_pattern_match_simple(pattern, buffer); + + g_free(buffer); + g_free(pattern); + return result; +} + +void +bookmarks_completion_setup(GtkEntryCompletion *location_completion, GtkTreeModel *tree_model) +{ + gtk_entry_completion_set_model(location_completion, tree_model); + gtk_entry_completion_set_text_column(location_completion, 0); + gtk_entry_completion_set_match_func(location_completion, location_completion_matches, NULL, NULL); + gtk_entry_completion_set_inline_selection(location_completion, BADWOLF_LOCATION_INLINE_SELECTION); +} + +static void +location_completion_cleanup(xmlXPathObjectPtr xpathObj, xmlXPathContextPtr xpathCtx, xmlDocPtr doc) +{ + if(xpathObj != NULL) xmlXPathFreeObject(xpathObj); + if(xpathCtx != NULL) xmlXPathFreeContext(xpathCtx); + if(doc != NULL) xmlFreeDoc(doc); +} + +static GtkTreeIter +load_xpath_results(GtkListStore *list_store, xmlNodeSetPtr nodes) +{ + GtkTreeIter iter; + int size; + + size = (nodes) ? nodes->nodeNr : 0; + + g_fprintf(stderr, "Bookmarks: Found %d bookmarks.\n", size); + for(int i = 0; i < size; i++) + if(nodes->nodeTab[i]) + { + gtk_list_store_append(list_store, &iter); + gtk_list_store_set( + list_store, &iter, 0, (char *)xmlXPathCastNodeToString(nodes->nodeTab[i]), -1); + } + + return iter; +} + +GtkTreeModel * +bookmarks_completion_init() +{ + const xmlChar *xpathExpr = "//bookmark/@href"; + char *filename = g_build_filename(g_get_user_data_dir(), "badwolf", "bookmarks.xbel", NULL); + xmlDocPtr doc = NULL; + xmlXPathContextPtr xpathCtx = NULL; + xmlXPathObjectPtr xpathObj = NULL; + GtkTreeIter iter; + GtkListStore *list_store = gtk_list_store_new(1, G_TYPE_STRING); + + if(access(filename, R_OK) != 0) { + g_fprintf(stderr, "Bookmarks: No loadable file found at %s\n", filename); + return NULL; + } + + g_fprintf(stderr, "Bookmarks: loading at %s\n", filename); + doc = xmlParseFile(filename); + if(doc == NULL) + { + g_fprintf(stderr, "Bookmarks: unable to parse file \"%s\"\n", filename); + location_completion_cleanup(xpathObj, xpathCtx, doc); + return NULL; + } + + xpathCtx = xmlXPathNewContext(doc); + if(xpathCtx == NULL) + { + g_fprintf(stderr, "Bookmarks: unable to create new XPath context\n"); + location_completion_cleanup(xpathObj, xpathCtx, doc); + return NULL; + } + + xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); + if(xpathObj == NULL) + { + g_fprintf(stderr, "Bookmarks: unable to evaluate xpath expression \"%s\"\n", xpathExpr); + location_completion_cleanup(xpathObj, xpathCtx, doc); + return NULL; + } + + iter = load_xpath_results(list_store, xpathObj->nodesetval); + + location_completion_cleanup(xpathObj, xpathCtx, doc); + + g_fprintf(stderr, "Bookmarks: Done.\n"); + + return GTK_TREE_MODEL(list_store); +} diff --git a/bookmarks.h b/bookmarks.h @@ -0,0 +1,3 @@ +#include <gtk/gtk.h> +GtkTreeModel *bookmarks_completion_init(); +void bookmarks_completion_setup(GtkEntryCompletion *location_completion, GtkTreeModel *tree_model); diff --git a/config.h b/config.h @@ -104,4 +104,7 @@ */ #define BADWOLF_DOWNLOAD_FILE_PATH_ELLIPSIZE PANGO_ELLIPSIZE_MIDDLE +// BADWOLF_LOCATION_INLINE_SELECTION: show selected completion as a selection in location entry +#define BADWOLF_LOCATION_INLINE_SELECTION TRUE + #endif /* CONFIG_H_INCLUDED */