From 12cbd061058a5e5a23380fce66169d34af3de746 Mon Sep 17 00:00:00 2001 From: Syndamia Date: Tue, 19 Jul 2022 14:18:16 +0300 Subject: code: Renamed codebase to goodwolf --- .gitignore | 2 +- Makefile | 42 +- badwolf.1 | 147 --- badwolf.c | 1329 -------------------- badwolf.desktop | 15 - badwolf.fr.1 | 166 --- badwolf.h | 51 - badwolf.inkscape.svg | 161 --- badwolf.svg | 129 -- bookmarks.c | 6 +- .../full/badwolf/bookmarks.xbel | 16 - .../full/goodwolf/bookmarks.xbel | 16 + config.h | 66 +- configure | 6 +- downloads.c | 12 +- downloads.h | 6 +- fmt.c | 4 +- fmt.h | 2 +- goodwolf.1 | 147 +++ goodwolf.c | 1329 ++++++++++++++++++++ goodwolf.desktop | 15 + goodwolf.fr.1 | 164 +++ goodwolf.h | 51 + goodwolf.inkscape.svg | 161 +++ goodwolf.svg | 129 ++ icons/hicolor/128x128/apps/badwolf.png | Bin 8666 -> 0 bytes icons/hicolor/128x128/apps/goodwolf.png | Bin 0 -> 8666 bytes icons/hicolor/24x24/apps/badwolf.png | Bin 1054 -> 0 bytes icons/hicolor/24x24/apps/goodwolf.png | Bin 0 -> 1054 bytes icons/hicolor/256x256/apps/badwolf.png | Bin 20138 -> 0 bytes icons/hicolor/256x256/apps/goodwolf.png | Bin 0 -> 20138 bytes icons/hicolor/32x32/apps/badwolf.png | Bin 1506 -> 0 bytes icons/hicolor/32x32/apps/goodwolf.png | Bin 0 -> 1506 bytes icons/hicolor/48x48/apps/badwolf.png | Bin 2552 -> 0 bytes icons/hicolor/48x48/apps/goodwolf.png | Bin 0 -> 2552 bytes icons/hicolor/64x64/apps/badwolf.png | Bin 3693 -> 0 bytes icons/hicolor/64x64/apps/goodwolf.png | Bin 0 -> 3693 bytes icons/hicolor/scalable/apps/badwolf.svg | 2 - icons/hicolor/scalable/apps/goodwolf.svg | 2 + keybindings.c | 14 +- keybindings.h | 2 +- po/manpage.pot | 184 +-- po/messages.pot | 74 +- uri.c | 2 +- uri.h | 4 +- uri_test.c | 10 +- usr.bin.badwolf | 81 -- usr.bin.goodwolf | 81 ++ 48 files changed, 2313 insertions(+), 2315 deletions(-) delete mode 100644 badwolf.1 delete mode 100644 badwolf.c delete mode 100644 badwolf.desktop delete mode 100644 badwolf.fr.1 delete mode 100644 badwolf.h delete mode 100644 badwolf.inkscape.svg delete mode 100644 badwolf.svg delete mode 100644 bookmarks_test.fixtures/full/badwolf/bookmarks.xbel create mode 100644 bookmarks_test.fixtures/full/goodwolf/bookmarks.xbel create mode 100644 goodwolf.1 create mode 100644 goodwolf.c create mode 100644 goodwolf.desktop create mode 100644 goodwolf.fr.1 create mode 100644 goodwolf.h create mode 100644 goodwolf.inkscape.svg create mode 100644 goodwolf.svg delete mode 100644 icons/hicolor/128x128/apps/badwolf.png create mode 100644 icons/hicolor/128x128/apps/goodwolf.png delete mode 100644 icons/hicolor/24x24/apps/badwolf.png create mode 100644 icons/hicolor/24x24/apps/goodwolf.png delete mode 100644 icons/hicolor/256x256/apps/badwolf.png create mode 100644 icons/hicolor/256x256/apps/goodwolf.png delete mode 100644 icons/hicolor/32x32/apps/badwolf.png create mode 100644 icons/hicolor/32x32/apps/goodwolf.png delete mode 100644 icons/hicolor/48x48/apps/badwolf.png create mode 100644 icons/hicolor/48x48/apps/goodwolf.png delete mode 100644 icons/hicolor/64x64/apps/badwolf.png create mode 100644 icons/hicolor/64x64/apps/goodwolf.png delete mode 100644 icons/hicolor/scalable/apps/badwolf.svg create mode 100644 icons/hicolor/scalable/apps/goodwolf.svg delete mode 100644 usr.bin.badwolf create mode 100644 usr.bin.goodwolf diff --git a/.gitignore b/.gitignore index b1e22a0..d058ab2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/badwolf +/goodwolf /locale /config.mk *.o diff --git a/Makefile b/Makefile index 135e5bd..66057a7 100644 --- a/Makefile +++ b/Makefile @@ -5,16 +5,16 @@ include config.mk -SRCS = bookmarks.c fmt.c fmt_test.c uri.c uri_test.c keybindings.c downloads.c badwolf.c -OBJS = bookmarks.o fmt.o uri.o keybindings.o downloads.o badwolf.o +SRCS = bookmarks.c fmt.c fmt_test.c uri.c uri_test.c keybindings.c downloads.c goodwolf.c +OBJS = bookmarks.o fmt.o uri.o keybindings.o downloads.o goodwolf.o OBJS_test = fmt_test.o uri_test.o bookmarks_test.o -EXE = badwolf +EXE = goodwolf EXE_test = fmt_test uri_test bookmarks_test TRANS = fr.mo pt_BR.mo tr.mo de.mo vi.mo -TRANS_MAN = badwolf.fr.1 -DOCS = usr.bin.badwolf README.md KnowledgeBase.md interface.txt +TRANS_MAN = goodwolf.fr.1 +DOCS = usr.bin.goodwolf README.md KnowledgeBase.md interface.txt -GETTEXT_OPTS = --copyright-holder="Badwolf Authors " --package-name="$(PACKAGE)" --package-version="$(VERSION_FULL)" --msgid-bugs-address="contact+badwolf-msgid@hacktivis.me" +GETTEXT_OPTS = --copyright-holder="Goodwolf Authors " --package-name="$(PACKAGE)" --package-version="$(VERSION_FULL)" --msgid-bugs-address="contact+goodwolf-msgid@hacktivis.me" all: config.mk $(EXE) $(TRANS) po/messages.pot $(TRANS_MAN) po/manpage.pot @@ -24,22 +24,22 @@ config.mk: configure icons: $(ICON_SIZES) -icons/hicolor/scalable/apps/badwolf.svg: badwolf.svg +icons/hicolor/scalable/apps/goodwolf.svg: goodwolf.svg mkdir -p icons/hicolor/scalable/apps scour --no-line-breaks --enable-id-stripping --remove-metadata $< $@ -icons/hicolor/%/apps/badwolf.png: icons/hicolor/scalable/apps/badwolf.svg +icons/hicolor/%/apps/goodwolf.png: icons/hicolor/scalable/apps/goodwolf.svg mkdir -p `dirname $@` $(INKSCAPE) `echo $@ | cut -d/ -f3 | ./icons_size.sh` $< -o $@ po/messages.pot: $(SRCS) xgettext --keyword=_ --language=C --from-code=UTF-8 -o $@ --add-comments --sort-output $(GETTEXT_OPTS) $(SRCS) -po/manpage.pot: badwolf.1 - po4a-gettextize --format man -M utf-8 --master badwolf.1 $(GETTEXT_OPTS) --po $@ +po/manpage.pot: goodwolf.1 + po4a-gettextize --format man -M utf-8 --master goodwolf.1 $(GETTEXT_OPTS) --po $@ -po/%_man.po: po/manpage.pot badwolf.1 - po4a-updatepo --format man -M utf-8 --master badwolf.1 --msgmerge-opt '--update' $(GETTEXT_OPTS) --po $@ +po/%_man.po: po/manpage.pot goodwolf.1 + po4a-updatepo --format man -M utf-8 --master goodwolf.1 --msgmerge-opt '--update' $(GETTEXT_OPTS) --po $@ po/%.po: po/messages.pot msgmerge --update --backup=off $@ $< @@ -48,10 +48,10 @@ ${TRANS}: po/${@:.mo=.po} mkdir -p locale/${@:.mo=}/LC_MESSAGES $(MSGFMT) -o locale/${@:.mo=}/LC_MESSAGES/$(PACKAGE).mo po/${@:.mo=.po} -badwolf.fr.1: po/fr_man.po badwolf.1 - po4a-translate --format man -M utf-8 --master badwolf.1 --po po/fr_man.po --localized $@ +goodwolf.fr.1: po/fr_man.po goodwolf.1 + po4a-translate --format man -M utf-8 --master goodwolf.1 --po po/fr_man.po --localized $@ -badwolf: $(OBJS) +goodwolf: $(OBJS) $(CC) -std=c11 -o $@ $(OBJS) $(LDFLAGS) $(LIBS) .c: @@ -78,29 +78,29 @@ test: $(EXE_test) .PHONY: lint lint: - $(MANDOC) -Tlint -Wunsupp,error,warning ./badwolf.1 $(TRANS_MAN) + $(MANDOC) -Tlint -Wunsupp,error,warning ./goodwolf.1 $(TRANS_MAN) $(SHELLCHECK) ./configure $(FLAWFINDER) . .PHONY: install install: all mkdir -p $(DESTDIR)$(BINDIR) - cp -p badwolf $(DESTDIR)$(BINDIR)/ + cp -p goodwolf $(DESTDIR)$(BINDIR)/ mkdir -p $(DESTDIR)$(MANDIR)/man1 - cp -p badwolf.1 $(DESTDIR)$(MANDIR)/man1/ + cp -p goodwolf.1 $(DESTDIR)$(MANDIR)/man1/ # TODO: use $TRANS_MAN mkdir -p $(DESTDIR)$(MANDIR)/fr/man1 - cp -p badwolf.fr.1 $(DESTDIR)$(MANDIR)/fr/man1/badwolf.1 + cp -p goodwolf.fr.1 $(DESTDIR)$(MANDIR)/fr/man1/goodwolf.1 mkdir -p $(DESTDIR)$(DATADIR)/locale cp -r locale/ $(DESTDIR)$(DATADIR)/ cp interface.css $(DESTDIR)$(DATADIR)/ mkdir -p $(DESTDIR)$(APPSDIR) - cp -p badwolf.desktop $(DESTDIR)$(APPSDIR)/ + cp -p goodwolf.desktop $(DESTDIR)$(APPSDIR)/ mkdir -p $(DESTDIR)$(DOCDIR) cp -p $(DOCS) $(DESTDIR)$(DOCDIR)/ mkdir -p $(DESTDIR)$(PREFIX)/share cp -r icons $(DESTDIR)$(PREFIX)/share/ - @printf '\nNote: An example AppArmor profile has been installed at '$(DOCDIR)/usr.bin.badwolf'\n' + @printf '\nNote: An example AppArmor profile has been installed at '$(DOCDIR)/usr.bin.goodwolf'\n' .PHONY: clean clean: diff --git a/badwolf.1 b/badwolf.1 deleted file mode 100644 index d173475..0000000 --- a/badwolf.1 +++ /dev/null @@ -1,147 +0,0 @@ -.\" BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser -.\" Copyright © 2019-2022 Badwolf Authors -.\" SPDX-License-Identifier: BSD-3-Clause -.Dd 2022-04-06 -.Dt BADWOLF 1 -.Os -.Sh NAME -.Nm badwolf -.Nd minimalist and privacy-oriented web browser based on WebKitGTK -.Sh SYNOPSIS -.Nm -.Op Ar webkit/gtk options -.Op Ar URLs or paths -.Sh DESCRIPTION -.Nm -is a minimalist browser that cares about privacy, it is based on WebKitGTK and thus also accepts WebKitGTK (and dependencies) flags and environment variables, unfortunately there doesn't seems to be manpages for theses. -.Pp -Runtime configuration specific to -.Nm -will probably get added at a later release. -.Sh KEYBINDINGS -The following section lists the keybinding by their action, each item is described by the widget the focus is on or -.Aq any -if it works for the whole window, followed by the keybind it grabs. -.Bl -tag -width Ds -.It webview Ctrl-Scroll -Zooms the webpage in/out. -.It webview Ctrl-0 -Resets webpage zoom to 100%. -.It any Ctrl-t -Creates a new tab (in a new session, similar as pressing the button) -.It browser Ctrl-F4, browser Alt-d -Closes the current tab -.It browser Ctrl-f -Focuses on the search entry -.It browser Ctrl-l -Focuses on the location(URL) entry -.It browser Ctrl-Shift-r / Ctrl-r, browser F5 -Reloads the content in the current tab (with/without clearing cache) -.It browser Escape -Stops loading the content in the current tab -.It browser F7 -Toggles caret browsing. -.It browser F12 -Opens the web inspector. -.It browser Ctrl-[ / Ctrl-] -Go back/forward in current tab's history -.It browser Ctrl-p -Print the current page. (spawns a dialog) -.It any Alt-Left / Alt-Right -Go to the previous/next tab -.It any F1 -Shows the about dialog -.It any Alt-n -Where n is any numeric-row key. -Go to the n-th tab, 0 goes to the last one. -.El -.Ss DEFAULT ONES -Here is a incomplete list of the default Webkit/GTK keybindings: -.Bl -tag -width Ds -.It any Ctrl-PageUp / Ctrl-PageDown -Go to the previous/next tab -.It search Ctrl-g / Ctrl-Shift-g -When the search box is focused it goes to the Next/Previous search term. -.It search Escape -Cancels current search -.El -.Sh ENVIRONMENT -.Bl -tag -width Ds -.It Ev BADWOLF_L10N -A colon-separated list in the form lang_COUNTRY where lang is in ISO-639 and COUNTRY in ISO-3166. -For example -.Ic BADWOLF_L10N="en_GB:fr_FR:de_DE" . -When this variable isn't set, spelling isn't activated. -A more generic variable name is also intended to be used in the future. -.Pp -To get the list of supported dictionaries execute -.Ic enchant-lsmod-2 -list-dicts -or before enchant 2.0: -.Ic enchant-lsmod -list-dicts -.El -.Sh FILES -The following paths are using -.Xr sh 1 -syntax to correctly support XDG Base Directory Specification, you can use the -.Xr echo 1 -command to check where it is on your system. -.Pp -.Bl -tag -width Ds -compact -.It Pa ${XDG_CONFIG_HOME:-$HOME/.config}/badwolf/content-filters.json -WebKit-specific content-filter file, this allows to block unwanted content (ads, nagware, ...). -For some introductory information about the format see: -.Lk https://webkit.org/blog/3476/content-blockers-first-look/ -.Lk https://webkit.org/blog/4062/targeting-domains-with-content-blockers/ -.Lk https://developer.apple.com/documentation/safariservices/creating_a_content_blocker -.Pp -For a converter using AblockPlus-style filters, try: -.Lk https://gitlab.com/eyeo/adblockplus/abp2blocklist -.Pp -For a ready-to-use file (that you should update periodically), try: -.Lk https://easylist-downloads.adblockplus.org/easylist_min_content_blocker.json -.It Pa ${XDG_CACHE_HOME:-$HOME/.cache}/badwolf/filters -This is where the compiled filters are stored, the file(s) in it are automatically generated and so shouldn't be edited. -Documented here only for sandboxing / access-control purposes. -.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 but you might also want to use XInclude to merge multiple XBEL files. -.Pp -For more information about this format see: -.Lk http://pyxml.sourceforge.net/topics/xbel/ -.Pp -For an example XBEL file see: -.Lk https://hacktivis.me/bookmarks.xbel -.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/webkit-web-extension/ -Directory containing the -.Lk https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebExtension.html WebKitWebExtensions -to be loaded into -.Nm . Note: They aren't the JavaScript-based Web-Extensions supported by Firefox or Chrome, but native code in shared objects using the WebKitGTK API. -.Pp -Examples of useful extensions may be found at: -.Lk https://hacktivis.me/git/badwolf-extensions -.It Pa ${DATADIR:-/usr/local/share}/badwolf/interface.css -.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/interface.css -CSS files (respectively system and user-level) for styling -.Nm -interface. -See -.\" GNOME can't even into doing any redirections of the few docs available -.Lk http://web.archive.org/web/20210420214617/https://developer.gnome.org/gtk3/stable/chap-css-properties.html -for the properties being available. -.Pp -For testing your styles I would recommend using the -.Ev GTK_DEBUG=interactive -environment variable on launching -.Nm -and going to the CSS tab. -.El -.Sh AUTHORS -.An Haelwenn (lanodan) Monnier Aq Mt contact+badwolf@hacktivis.me -.Sh BUGS -You can submit contributions or tickets to -.Lk https://sr.ht/~lanodan/badwolf/ -with -.Xr git-send-email 1 -for patches. diff --git a/badwolf.c b/badwolf.c deleted file mode 100644 index 51989e1..0000000 --- a/badwolf.c +++ /dev/null @@ -1,1329 +0,0 @@ -// BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser -// Copyright © 2019-2021 Badwolf Authors -// SPDX-License-Identifier: BSD-3-Clause - -#include "badwolf.h" - -#include "bookmarks.h" -#include "config.h" -#include "downloads.h" -#include "fmt.h" -#include "keybindings.h" -#include "uri.h" - -#include -#include /* _() and other internationalization/localization helpers */ -#include /* soup* */ -#include /* LC_* */ -#include /* perror(), fprintf(), snprintf() */ -#include /* malloc() */ -#include /* access() */ - -const gchar *homepage = "https://hacktivis.me/projects/badwolf"; -const gchar *version = VERSION; - -static gchar *web_extensions_directory; -static uint64_t context_id_counter = 0; -GtkTreeModel *bookmarks_completion_model; - -static gboolean tabs_no_label = false; -static gboolean tabs_constant = false; -static gboolean tabs_context_label = false; -static gboolean tray_enabled = false; -static gboolean alt_useragent = false; -static int custom_favicon_size = 30; -static gboolean persistent_storage = false; -static gboolean separated_storage = false; - -static gboolean WebViewCb_close(WebKitWebView *webView, gpointer user_data); -static gboolean WebViewCb_web_process_terminated(WebKitWebView *webView, - WebKitWebProcessTerminationReason reason, - gpointer user_data); -static gboolean -WebViewCb_notify__uri(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); -static gboolean -WebViewCb_notify__title(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); -static gboolean -WebViewCb_notify__favicon(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); -static gboolean -WebViewCb_notify__is__playing__audio(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); -static gboolean WebViewCb_notify__estimated_load_progress(WebKitWebView *webView, - GParamSpec *pspec, - gpointer user_data); -static gboolean WebViewCb_mouse_target_changed(WebKitWebView *webView, - WebKitHitTestResult *hit, - guint modifiers, - gpointer user_data); -static WebKitWebView *WebViewCb_create(WebKitWebView *related_web_view, - WebKitNavigationAction *navigation_action, - gpointer user_data); -static gboolean WebViewCb_permission_request(WebKitWebView *web_view, - WebKitPermissionRequest *request, - gpointer user_data); -static gboolean WebViewCb_decide_policy(WebKitWebView *web_view, - WebKitPolicyDecision *decision, - WebKitPolicyDecisionType decision_type, - gpointer user_data); -static void -WebViewCb_load_changed(WebKitWebView *webView, WebKitLoadEvent load_event, gpointer user_data); -static void web_contextCb_download_started(WebKitWebContext *web_context, - WebKitDownload *download, - gpointer user_data); -static gboolean locationCb_activate(GtkEntry *location, gpointer user_data); -static gboolean javascriptCb_toggled(GtkButton *javascript, gpointer user_data); -static gboolean auto_load_imagesCb_toggled(GtkButton *auto_load_images, gpointer user_data); -static void backCb_clicked(GtkButton *back, gpointer user_data); -static void forwardCb_clicked(GtkButton *forward, gpointer user_data); -static void printCb_clicked(GtkButton *forward, gpointer user_data); -static gboolean SearchEntryCb_next__match(GtkSearchEntry *search, gpointer user_data); -static gboolean SearchEntryCb_previous__match(GtkSearchEntry *search, gpointer user_data); -static gboolean SearchEntryCb_search__changed(GtkSearchEntry *search, gpointer user_data); -static gboolean SearchEntryCb_stop__search(GtkSearchEntry *search, gpointer user_data); -static void new_tabCb_clicked(GtkButton *new_tab, gpointer user_data); -static void closeCb_clicked(GtkButton *close, gpointer user_data); -static void -notebookCb_switch__page(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data); -void content_managerCb_ready(GObject *store, GAsyncResult *result, gpointer user_data); - -static gboolean -WebViewCb_close(WebKitWebView *webView, gpointer user_data) -{ - (void)webView; - struct Client *browser = (struct Client *)user_data; - - gtk_widget_destroy(browser->box); - - free(browser); - - return TRUE; -} - -static gboolean -WebViewCb_web_process_terminated(WebKitWebView *webView, - WebKitWebProcessTerminationReason reason, - gpointer user_data) -{ - (void)webView; - struct Client *browser = (struct Client *)user_data; - - switch(reason) - { - case WEBKIT_WEB_PROCESS_CRASHED: - fprintf(stderr, "%s", _("the web process crashed.\n")); - webView_tab_label_change(browser, _("Crashed")); - break; - case WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT: - fprintf(stderr, "%s", _("the web process exceeded the memory limit.\n")); - webView_tab_label_change(browser, _("Out of Memory")); - break; - default: - fprintf(stderr, "%s", _("the web process terminated for an unknown reason.\n")); - webView_tab_label_change(browser, _("Unknown Crash")); - } - - return FALSE; -} - -static gboolean -WebViewCb_notify__uri(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data) -{ - (void)webView; - (void)pspec; - const gchar *location_uri; - struct Client *browser = (struct Client *)user_data; - - location_uri = webkit_web_view_get_uri(browser->webView); - - gtk_entry_set_text(GTK_ENTRY(browser->location), location_uri); - - if(webkit_uri_for_display(location_uri) != location_uri) - gtk_widget_set_tooltip_text(browser->location, webkit_uri_for_display(location_uri)); - else - gtk_widget_set_has_tooltip(browser->location, false); - - return TRUE; -} - -cairo_surface_t* scale_favicon(cairo_surface_t *f) -{ - if (f == NULL) return NULL; - gint pixel_size = custom_favicon_size; - if (pixel_size == 0) { - gtk_icon_size_lookup(GTK_ICON_SIZE_SMALL_TOOLBAR, NULL, &pixel_size); - if (pixel_size == 0) return NULL; - } - - cairo_surface_t *result = cairo_surface_create_similar(f, - cairo_surface_get_content(f), - pixel_size, - pixel_size); - cairo_t *cr = cairo_create(result); - cairo_scale(cr, - (double)pixel_size/cairo_image_surface_get_width(f), - (double)pixel_size/cairo_image_surface_get_height(f)); - cairo_set_source_surface(cr, f, 0, 0); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_paint(cr); - cairo_destroy(cr); - return result; -} - -GtkWidget * -badwolf_new_tab_box(const gchar *title, struct Client *browser) -{ - (void)browser; - /* flawfinder: ignore. bound checks are done */ - char context_id_str[BADWOLF_CTX_SIZ] = {0, 0, 0, 0, 0, 0, 0}; - - fmt_context_id(browser->context_id, context_id_str, 1); - - GtkWidget *tab_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_set_name(tab_box, "browser__tabbox"); - - GtkWidget *close = - gtk_button_new_from_icon_name("window-close-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); - gtk_widget_set_name(close, "browser__tabbox__close"); - GtkWidget *context_label; - GtkWidget *context_label_event_box; - if (tabs_context_label) { - context_label = gtk_label_new(context_id_str); - gtk_widget_set_name(context_label, "browser__tabbox__context_label"); - context_label_event_box = gtk_event_box_new(); - gtk_container_add(GTK_CONTAINER(context_label_event_box), context_label); - } - GtkWidget *favicon = - gtk_image_new_from_surface(scale_favicon(webkit_web_view_get_favicon(browser->webView))); - gtk_widget_set_name(favicon, "browser__tabbox__favicon"); - GtkWidget *favicon_event_box = gtk_event_box_new(); - gtk_container_add(GTK_CONTAINER(favicon_event_box), favicon); - GtkWidget *label = gtk_label_new(title); - gtk_widget_set_name(label, "browser__tabbox__label"); - GtkWidget *label_event_box = gtk_event_box_new(); - gtk_container_add(GTK_CONTAINER(label_event_box), label); - GtkWidget *playing = - gtk_image_new_from_icon_name("audio-volume-high-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_widget_set_name(playing, "browser__tabbox__playing"); - GtkWidget *playing_event_box = gtk_event_box_new(); - gtk_container_add(GTK_CONTAINER(playing_event_box), playing); - -#ifdef BADWOLF_TAB_BOX_WIDTH - gtk_widget_set_size_request(label, BADWOLF_TAB_BOX_WIDTH, -1); -#endif -#ifdef BADWOLF_TAB_LABEL_CHARWIDTH - gtk_label_set_width_chars(GTK_LABEL(label), BADWOLF_TAB_LABEL_CHARWIDTH); -#endif - gtk_widget_set_hexpand(tab_box, BADWOLF_TAB_HEXPAND); - - gtk_label_set_ellipsize(GTK_LABEL(label), BADWOLF_TAB_LABEL_ELLIPSIZE); - gtk_label_set_single_line_mode(GTK_LABEL(label), TRUE); - - if (tabs_context_label) { - gtk_label_set_single_line_mode(GTK_LABEL(context_label), TRUE); - gtk_box_pack_start(GTK_BOX(tab_box), context_label_event_box, TRUE, TRUE, 0); - } - - gtk_box_pack_start(GTK_BOX(tab_box), favicon_event_box, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tab_box), playing_event_box, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tab_box), label_event_box, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(tab_box), close, FALSE, FALSE, 0); - - gtk_button_set_relief(GTK_BUTTON(close), GTK_RELIEF_NONE); - - g_signal_connect(close, "clicked", G_CALLBACK(closeCb_clicked), browser); - - gtk_widget_set_tooltip_text(tab_box, title); - - gtk_widget_show_all(tab_box); - gtk_widget_set_visible(playing, webkit_web_view_is_playing_audio(browser->webView)); - gtk_widget_set_visible(label, !tabs_no_label); - gtk_widget_set_visible(close, !tabs_constant); - gtk_widget_set_events(label, GDK_BUTTON_RELEASE_MASK); - g_signal_connect( - tab_box, "button-release-event", G_CALLBACK(tab_boxCb_button_release_event), browser); - - return tab_box; -} - -static gboolean -WebViewCb_notify__title(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data) -{ - (void)webView; - (void)pspec; - struct Client *browser = (struct Client *)user_data; - - webView_tab_label_change(browser, NULL); - - return TRUE; -} - -static gboolean -WebViewCb_notify__is__playing__audio(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data) -{ - (void)webView; - (void)pspec; - struct Client *browser = (struct Client *)user_data; - - webView_tab_label_change(browser, NULL); - - return TRUE; -} - -static gboolean -WebViewCb_notify__favicon(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data) -{ - (void)webView; - (void)pspec; - struct Client *browser = (struct Client *)user_data; - - webView_tab_label_change(browser, NULL); - - return TRUE; -} - -void -webView_tab_label_change(struct Client *browser, const gchar *title) -{ - GtkWidget *notebook = browser->window->notebook; - -#define title_IS_EMPTY (title == NULL) || strnlen(title, 2) == 0 - - if(title_IS_EMPTY) title = webkit_web_view_get_title(browser->webView); - if(title_IS_EMPTY) title = webkit_web_view_get_uri(browser->webView); - if(title_IS_EMPTY) title = "BadWolf"; - - gtk_notebook_set_tab_label( - GTK_NOTEBOOK(notebook), browser->box, badwolf_new_tab_box(title, browser)); - gtk_notebook_set_menu_label_text(GTK_NOTEBOOK(notebook), browser->box, title); - - // Set the window title if the title change was on the current tab - if(gtk_notebook_page_num(GTK_NOTEBOOK(notebook), browser->box) == - gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))) - gtk_window_set_title(GTK_WINDOW(browser->window->main_window), title); -} - -static gboolean -WebViewCb_notify__estimated_load_progress(WebKitWebView *webView, - GParamSpec *pspec, - gpointer user_data) -{ - (void)webView; - (void)pspec; - struct Client *browser = (struct Client *)user_data; - gdouble progress; - - progress = webkit_web_view_get_estimated_load_progress(browser->webView); - - if(progress >= 1) progress = 0; - - gtk_entry_set_progress_fraction(GTK_ENTRY(browser->location), progress); - - return TRUE; -} - -static gboolean -WebViewCb_mouse_target_changed(WebKitWebView *webView, - WebKitHitTestResult *hit, - guint modifiers, - gpointer user_data) -{ - (void)webView; - (void)modifiers; - struct Client *browser = (struct Client *)user_data; - - if(webkit_hit_test_result_context_is_link(hit)) - { - const gchar *link_uri = webkit_hit_test_result_get_link_uri(hit); - - gtk_label_set_text(GTK_LABEL(browser->statuslabel), webkit_uri_for_display(link_uri)); - } - else - gtk_label_set_text(GTK_LABEL(browser->statuslabel), NULL); - - return FALSE; -} - -static gboolean -WebViewCb_scroll_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - (void)widget; - struct Client *browser = (struct Client *)data; - gdouble delta_x, delta_y; - gdouble zoom; - - if(((GdkEventScroll *)event)->state & GDK_CONTROL_MASK) - { - gdk_event_get_scroll_deltas(event, &delta_x, &delta_y); - zoom = webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(browser->webView)); - zoom -= delta_y * 0.1; - webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(browser->webView), zoom); - return TRUE; - } - - return FALSE; -} - -static WebKitWebView * -WebViewCb_create(WebKitWebView *related_web_view, - WebKitNavigationAction *navigation_action, - gpointer user_data) -{ - (void)navigation_action; - struct Client *old_browser = (struct Client *)user_data; - struct Client *browser = NULL; - - // shouldn't be needed but better be safe - old_browser->webView = related_web_view; - - browser = new_browser(old_browser->window, NULL, old_browser); - - if(badwolf_new_tab(GTK_NOTEBOOK(old_browser->window->notebook), browser, FALSE) < 0) - return NULL; - else - return browser->webView; -} - -static gboolean -WebViewCb_permission_request(WebKitWebView *web_view, - WebKitPermissionRequest *request, - gpointer user_data) -{ - (void)web_view; - (void)user_data; - - webkit_permission_request_deny(request); - - return TRUE; /* Stop other handlers */ -} - -static gboolean -WebViewCb_decide_policy(WebKitWebView *web_view, - WebKitPolicyDecision *decision, - WebKitPolicyDecisionType decision_type, - gpointer user_data) -{ - WebKitResponsePolicyDecision *r; - (void)web_view; - (void)user_data; - - switch(decision_type) - { - case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: - r = WEBKIT_RESPONSE_POLICY_DECISION(decision); - if(!webkit_response_policy_decision_is_mime_type_supported(r)) - webkit_policy_decision_download(decision); - else - webkit_policy_decision_use(decision); - break; - default: - /* Use whatever default there is. */ - return FALSE; - } - - return TRUE; -} - -static void -WebViewCb_load_changed(WebKitWebView *webView, WebKitLoadEvent load_event, gpointer user_data) -{ - (void)webView; - (void)load_event; - struct Client *browser = (struct Client *)user_data; - - gtk_widget_set_sensitive(browser->back, webkit_web_view_can_go_back(browser->webView)); - gtk_widget_set_sensitive(browser->forward, webkit_web_view_can_go_forward(browser->webView)); -} - -static char * -detail_tls_certificate_flags(GTlsCertificateFlags tls_errors) -{ - GString *errors = g_string_new(NULL); - - g_string_append_printf(errors, - _("Couldn't verify the TLS certificate to ensure a better security of the " - "connection. You might want to verify your machine and network.\n\n")); - - if(tls_errors & G_TLS_CERTIFICATE_UNKNOWN_CA) - g_string_append_printf(errors, _("Error: The X509 Certificate Authority is unknown.\n")); - - if(tls_errors & G_TLS_CERTIFICATE_BAD_IDENTITY) - g_string_append(errors, _("Error: The given identity doesn't match the expected one.\n")); - - if(tls_errors & G_TLS_CERTIFICATE_NOT_ACTIVATED) - g_string_append(errors, - _("Error: The certificate isn't valid yet. Check your system's clock.\n")); - - if(tls_errors & G_TLS_CERTIFICATE_EXPIRED) - g_string_append(errors, _("Error: The certificate has expired. Check your system's clock.\n")); - - if(tls_errors & G_TLS_CERTIFICATE_REVOKED) - g_string_append(errors, _("Error: The certificate has been revoked.\n")); - - if(tls_errors & G_TLS_CERTIFICATE_INSECURE) - g_string_append(errors, _("Error: The certificate is considered to be insecure.\n")); - - if(tls_errors & G_TLS_CERTIFICATE_GENERIC_ERROR) - g_string_append(errors, _("Error: Some unknown error occurred validating the certificate.\n")); - - return g_string_free(errors, FALSE); -} - -static gboolean -WebViewCb_load_failed_with_tls_errors(WebKitWebView *web_view, - gchar *failing_text, - GTlsCertificate *certificate, - GTlsCertificateFlags errors, - gpointer user_data) -{ - (void)web_view; - (void)certificate; - (void)errors; - struct Client *browser = (struct Client *)user_data; - gchar *error_details = detail_tls_certificate_flags(errors); - gint dialog_response; - -#ifndef USE_LIBSOUP2 - GUri *failing_uri = g_uri_parse(failing_text, G_URI_FLAGS_NONE, NULL); -#else - SoupURI *failing_uri = soup_uri_new(failing_text); -#endif - - GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(browser->window->main_window), - GTK_DIALOG_MODAL & GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_NONE, - _("TLS Error for %s."), - failing_text); - gtk_dialog_add_buttons( - GTK_DIALOG(dialog), _("Temporarily Add Exception"), 1, _("Continue"), 0, NULL); - if(!failing_uri) - { - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), 1, FALSE); - } - gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0); - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s\n", error_details); - - dialog_response = gtk_dialog_run(GTK_DIALOG(dialog)); - - if(dialog_response == 1) - { -#ifndef USE_LIBSOUP2 - webkit_web_context_allow_tls_certificate_for_host( - webkit_web_view_get_context(browser->webView), certificate, g_uri_get_host(failing_uri)); -#else - webkit_web_context_allow_tls_certificate_for_host( - webkit_web_view_get_context(browser->webView), certificate, failing_uri->host); -#endif - webkit_web_view_reload(browser->webView); - } - -#ifndef USE_LIBSOUP2 - /* Calling g_free(failing_uri) ought to be the correct way but this causes a segfault. - * - * - documentation describes it as something which should be free - * - implementation seems to make it a pointer that should be freed - * - epiphany doesn't seems to free/unref it but gnome code seems to frequently have memleaks - * - * Decided to at least continue to try with using g_uri_unref(failing_uri) instead. - * Related fediverse post: - */ - g_uri_unref(failing_uri); -#else - soup_uri_free(failing_uri); -#endif - g_free(error_details); - gtk_widget_destroy(dialog); - - return FALSE; /* propagate the event further */ -} - -static void -web_contextCb_download_started(WebKitWebContext *web_context, - WebKitDownload *webkit_download, - gpointer user_data) -{ - (void)web_context; - struct Client *browser = (struct Client *)user_data; - struct Download *download = malloc(sizeof(struct Download)); - - assert(webkit_download); - - if(download != NULL) - { - download->window = browser->window; - - download_new_entry(webkit_download, download); - - g_signal_connect( - G_OBJECT(webkit_download), "received-data", G_CALLBACK(downloadCb_received_data), download); - g_signal_connect(G_OBJECT(webkit_download), - "created-destination", - G_CALLBACK(downloadCb_created_destination), - download); - g_signal_connect(G_OBJECT(webkit_download), "failed", G_CALLBACK(downloadCb_failed), download); - g_signal_connect( - G_OBJECT(webkit_download), "finished", G_CALLBACK(downloadCb_finished), download); - } - - g_signal_connect(G_OBJECT(webkit_download), - "decide-destination", - G_CALLBACK(downloadCb_decide_destination), - user_data); -} - -static gboolean -locationCb_activate(GtkEntry *location, gpointer user_data) -{ - struct Client *browser = (struct Client *)user_data; - - webkit_web_view_load_uri(browser->webView, - badwolf_ensure_uri_scheme(gtk_entry_get_text(location), TRUE)); - - return TRUE; -} - -static gboolean -javascriptCb_toggled(GtkButton *javascript, gpointer user_data) -{ - struct Client *browser = (struct Client *)user_data; - - WebKitSettings *settings = webkit_web_view_get_settings(browser->webView); - - webkit_settings_set_enable_javascript_markup( - settings, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(javascript))); - - webkit_web_view_set_settings(browser->webView, settings); - - return TRUE; -} - -static gboolean -auto_load_imagesCb_toggled(GtkButton *auto_load_images, gpointer user_data) -{ - struct Client *browser = (struct Client *)user_data; - - WebKitSettings *settings = webkit_web_view_get_settings(browser->webView); - - webkit_settings_set_auto_load_images( - settings, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(auto_load_images))); - - webkit_web_view_set_settings(browser->webView, settings); - - return TRUE; -} - -static void -backCb_clicked(GtkButton *back, gpointer user_data) -{ - (void)back; - struct Client *browser = (struct Client *)user_data; - - webkit_web_view_go_back(browser->webView); -} - -static void -forwardCb_clicked(GtkButton *forward, gpointer user_data) -{ - (void)forward; - struct Client *browser = (struct Client *)user_data; - - webkit_web_view_go_forward(browser->webView); -} - -static void -printCb_clicked(GtkButton *print, gpointer user_data) -{ - (void)print; - struct Client *browser = (struct Client *)user_data; - - WebKitPrintOperation *print_operation = webkit_print_operation_new(browser->webView); - - webkit_print_operation_run_dialog(print_operation, GTK_WINDOW(browser->window->main_window)); -} - -static gboolean -SearchEntryCb_next__match(GtkSearchEntry *search, gpointer user_data) -{ - (void)search; - struct Client *browser = (struct Client *)user_data; - WebKitFindController *findController = webkit_web_view_get_find_controller(browser->webView); - - webkit_find_controller_search_next(findController); - - return TRUE; -} - -static gboolean -SearchEntryCb_previous__match(GtkSearchEntry *search, gpointer user_data) -{ - (void)search; - struct Client *browser = (struct Client *)user_data; - WebKitFindController *findController = webkit_web_view_get_find_controller(browser->webView); - - webkit_find_controller_search_previous(findController); - - return TRUE; -} - -static gboolean -SearchEntryCb_search__changed(GtkSearchEntry *search, gpointer user_data) -{ - struct Client *browser = (struct Client *)user_data; - WebKitFindController *findController = webkit_web_view_get_find_controller(browser->webView); - const gchar *search_text = gtk_entry_get_text(GTK_ENTRY(search)); - - webkit_find_controller_search(findController, search_text, 0, 0); - - return TRUE; -} - -static gboolean -SearchEntryCb_stop__search(GtkSearchEntry *search, gpointer user_data) -{ - (void)search; - struct Client *browser = (struct Client *)user_data; - WebKitFindController *findController = webkit_web_view_get_find_controller(browser->webView); - - webkit_find_controller_search_finish(findController); - - return TRUE; -} - -static gboolean -widgetCb_drop_button3_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) -{ - (void)widget; - (void)user_data; - - // Button3 being right-click on right-handed mode, left-click on left-handed mode - return ((GdkEventButton *)event)->button == 3; -} - -struct Client * -new_browser(struct Window *window, const gchar *target_url, struct Client *old_browser) -{ - struct Client *browser = malloc(sizeof(struct Client)); - target_url = badwolf_ensure_uri_scheme(target_url, (old_browser == NULL)); - char *badwolf_l10n = NULL; - - WebKitWebContext *web_context; - - if(browser == NULL) return NULL; - - browser->window = window; - browser->context_id = old_browser == NULL ? context_id_counter++ : old_browser->context_id; - browser->box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - gtk_widget_set_name(browser->box, "browser__box"); - - browser->toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_set_name(browser->toolbar, "browser__toolbar"); - - browser->back = - gtk_button_new_from_icon_name("go-previous-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); - gtk_widget_set_name(browser->back, "browser__back"); - - browser->forward = gtk_button_new_from_icon_name("go-next-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_widget_set_name(browser->forward, "browser__forward"); - - GtkWidget *toolbar_separator = gtk_separator_new(GTK_ORIENTATION_VERTICAL); - - browser->javascript = gtk_toggle_button_new_with_mnemonic(_("_JS")); - gtk_widget_set_name(browser->javascript, "browser__javascript"); - gtk_widget_set_tooltip_text(browser->javascript, _("Toggle javascript")); - gtk_button_set_relief(GTK_BUTTON(browser->javascript), GTK_RELIEF_NONE); - - browser->auto_load_images = gtk_toggle_button_new_with_mnemonic(_("_IMG")); - gtk_widget_set_name(browser->auto_load_images, "browser__load_images"); - gtk_widget_set_tooltip_text(browser->auto_load_images, _("Toggle loading images automatically")); - gtk_button_set_relief(GTK_BUTTON(browser->auto_load_images), GTK_RELIEF_NONE); - - browser->location = gtk_entry_new(); - gtk_widget_set_name(browser->location, "browser__location"); - - GtkWidget *print = - gtk_button_new_from_icon_name("document-print-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_widget_set_name(browser->back, "browser__print"); - - browser->statusbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_set_name(browser->statusbar, "browser__statusbar"); - browser->search = gtk_search_entry_new(); - gtk_widget_set_name(browser->search, "browser__search"); - browser->statuslabel = gtk_label_new(NULL); - gtk_widget_set_name(browser->statuslabel, "browser__statuslabel"); - - if(old_browser == NULL) - { - WebKitWebsiteDataManager *website_data_manager = - (persistent_storage) ? webkit_website_data_manager_new(NULL) - : webkit_website_data_manager_new_ephemeral(); - webkit_website_data_manager_set_itp_enabled(website_data_manager, TRUE); - - web_context = webkit_web_context_new_with_website_data_manager(website_data_manager); - g_object_unref(website_data_manager); - webkit_web_context_set_sandbox_enabled(web_context, TRUE); - webkit_web_context_set_process_model(web_context, - WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES); - webkit_web_context_set_web_extensions_directory(web_context, web_extensions_directory); - webkit_web_context_set_favicon_database_directory(web_context, NULL); - if (persistent_storage) { - char context_id_str[BADWOLF_CTX_SIZ] = {0, 0, 0, 0, 0, 0, 0}; - if (separated_storage) { - fmt_context_id(browser->context_id, context_id_str, 0); - g_mkdir_with_parents( - g_build_filename(g_get_user_config_dir(), "badwolf", context_id_str, NULL), - 0755); - } - - webkit_cookie_manager_set_persistent_storage( - webkit_website_data_manager_get_cookie_manager(website_data_manager), - g_build_filename(g_get_user_config_dir(), "badwolf", context_id_str, "cookies.txt", NULL), - WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT); - webkit_cookie_manager_set_accept_policy( - webkit_website_data_manager_get_cookie_manager(website_data_manager), - WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); - } - - g_signal_connect(G_OBJECT(web_context), - "download-started", - G_CALLBACK(web_contextCb_download_started), - browser); - } - else - { - web_context = webkit_web_view_get_context(old_browser->webView); - } - - /* flawfinder: ignore. Consider that g_strsplit is safe enough */ - badwolf_l10n = getenv("BADWOLF_L10N"); - - if(badwolf_l10n != NULL) - { - gchar **languages = g_strsplit(badwolf_l10n, ":", -1); - webkit_web_context_set_spell_checking_languages(web_context, (const gchar *const *)languages); - g_strfreev(languages); - - webkit_web_context_set_spell_checking_enabled(web_context, TRUE); - } - - WebKitSettings *settings = webkit_settings_new_with_settings(BADWOLF_WEBKIT_SETTINGS); - if (alt_useragent == TRUE) - webkit_settings_set_user_agent(settings, "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:74.0) Gecko/20100101 Firefox/74.0"); - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(browser->javascript), - webkit_settings_get_enable_javascript_markup(settings)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(browser->auto_load_images), - webkit_settings_get_auto_load_images(settings)); - - browser->webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, - "web-context", - web_context, - "related-view", - old_browser == NULL ? NULL : old_browser->webView, - "settings", - settings, - "user-content-manager", - window->content_manager, - NULL)); - gtk_widget_set_name(GTK_WIDGET(browser->webView), "browser__webView"); - if(old_browser == NULL) - { - g_object_unref(web_context); - } - g_object_unref(settings); - - gtk_box_pack_start( - GTK_BOX(browser->toolbar), GTK_WIDGET(browser->back), FALSE, FALSE, BADWOLF_TOOLBAR_PADDING); - gtk_box_pack_start(GTK_BOX(browser->toolbar), - GTK_WIDGET(browser->forward), - FALSE, - FALSE, - BADWOLF_TOOLBAR_PADDING); - gtk_box_pack_start(GTK_BOX(browser->toolbar), - toolbar_separator, - FALSE, - FALSE, - BADWOLF_TOOLBAR_SEPARATOR_PADDING); - gtk_box_pack_start(GTK_BOX(browser->toolbar), - GTK_WIDGET(browser->javascript), - FALSE, - FALSE, - BADWOLF_TOOLBAR_PADDING); - gtk_box_pack_start(GTK_BOX(browser->toolbar), - GTK_WIDGET(browser->auto_load_images), - FALSE, - FALSE, - BADWOLF_TOOLBAR_PADDING); - gtk_box_pack_start(GTK_BOX(browser->toolbar), - GTK_WIDGET(browser->location), - TRUE, - TRUE, - BADWOLF_TOOLBAR_PADDING); - gtk_box_pack_start(GTK_BOX(browser->toolbar), print, FALSE, FALSE, BADWOLF_TOOLBAR_PADDING); - - gtk_container_set_focus_child(GTK_CONTAINER(browser->box), browser->toolbar); - gtk_container_set_focus_child(GTK_CONTAINER(browser->toolbar), browser->location); - - gtk_box_pack_start( - GTK_BOX(browser->box), GTK_WIDGET(browser->toolbar), FALSE, FALSE, BADWOLF_BOX_PADDING); - gtk_box_pack_start( - GTK_BOX(browser->box), GTK_WIDGET(browser->webView), TRUE, TRUE, BADWOLF_BOX_PADDING); - - gtk_box_pack_start( - GTK_BOX(browser->box), GTK_WIDGET(browser->statusbar), FALSE, FALSE, BADWOLF_BOX_PADDING); - - gtk_box_pack_start(GTK_BOX(browser->statusbar), - GTK_WIDGET(browser->search), - FALSE, - FALSE, - BADWOLF_STATUSBAR_PADDING); - gtk_box_pack_start(GTK_BOX(browser->statusbar), - GTK_WIDGET(browser->statuslabel), - FALSE, - FALSE, - BADWOLF_STATUSBAR_PADDING); - - gtk_widget_set_halign(browser->statusbar, GTK_ALIGN_START); - - 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); - - gtk_entry_set_placeholder_text(GTK_ENTRY(browser->search), _("search in current page")); - - /* signals for back/forward buttons */ - g_signal_connect(browser->back, "clicked", G_CALLBACK(backCb_clicked), browser); - g_signal_connect(browser->forward, "clicked", G_CALLBACK(forwardCb_clicked), browser); - /* prevents GtkNotebook from spawning it's context-menu */ - g_signal_connect( - browser->back, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); - g_signal_connect( - browser->back, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); - g_signal_connect( - browser->forward, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); - g_signal_connect( - browser->forward, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); - - /* signals for javacript toggle widget */ - g_signal_connect(browser->javascript, "toggled", G_CALLBACK(javascriptCb_toggled), browser); - /* prevents GtkNotebook from spawning it's context-menu */ - g_signal_connect( - browser->javascript, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); - g_signal_connect( - browser->javascript, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); - - /* signals for auto_load_images toggle widget */ - g_signal_connect( - browser->auto_load_images, "toggled", G_CALLBACK(auto_load_imagesCb_toggled), browser); - /* prevents GtkNotebook from spawning it's context-menu */ - g_signal_connect(browser->auto_load_images, - "button-press-event", - G_CALLBACK(widgetCb_drop_button3_event), - NULL); - g_signal_connect(browser->auto_load_images, - "button-release-event", - G_CALLBACK(widgetCb_drop_button3_event), - NULL); - - /* signals for location entry widget */ - g_signal_connect(browser->location, "activate", G_CALLBACK(locationCb_activate), browser); - - /* signals for print button */ - g_signal_connect(print, "clicked", G_CALLBACK(printCb_clicked), browser); - /* prevents GtkNotebook from spawning it's context-menu */ - g_signal_connect(print, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); - g_signal_connect(print, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); - - /* signals for WebView widget */ - g_signal_connect(browser->webView, - "web-process-terminated", - G_CALLBACK(WebViewCb_web_process_terminated), - browser); - g_signal_connect(browser->webView, "notify::uri", G_CALLBACK(WebViewCb_notify__uri), browser); - - g_signal_connect(browser->webView, "notify::title", G_CALLBACK(WebViewCb_notify__title), browser); - g_signal_connect(browser->webView, - "notify::favicon", - G_CALLBACK(WebViewCb_notify__favicon), - browser); - g_signal_connect(browser->webView, - "notify::is-playing-audio", - G_CALLBACK(WebViewCb_notify__is__playing__audio), - browser); - g_signal_connect(browser->webView, - "mouse-target-changed", - G_CALLBACK(WebViewCb_mouse_target_changed), - browser); - g_signal_connect(browser->webView, - "notify::estimated-load-progress", - G_CALLBACK(WebViewCb_notify__estimated_load_progress), - browser); - g_signal_connect(browser->webView, "create", G_CALLBACK(WebViewCb_create), browser); - g_signal_connect(browser->webView, "close", G_CALLBACK(WebViewCb_close), browser); - - g_signal_connect( - browser->webView, "key-press-event", G_CALLBACK(WebViewCb_key_press_event), browser); - g_signal_connect(browser->webView, "scroll-event", G_CALLBACK(WebViewCb_scroll_event), browser); - g_signal_connect( - browser->webView, "permission-request", G_CALLBACK(WebViewCb_permission_request), NULL); - g_signal_connect(browser->webView, "decide-policy", G_CALLBACK(WebViewCb_decide_policy), NULL); - g_signal_connect(browser->webView, - "load-failed-with-tls-errors", - G_CALLBACK(WebViewCb_load_failed_with_tls_errors), - browser); - g_signal_connect(browser->webView, "load-changed", G_CALLBACK(WebViewCb_load_changed), browser); - - /* signals for search widget */ - g_signal_connect(browser->search, "next-match", G_CALLBACK(SearchEntryCb_next__match), browser); - g_signal_connect( - browser->search, "previous-match", G_CALLBACK(SearchEntryCb_previous__match), browser); - g_signal_connect( - browser->search, "search-changed", G_CALLBACK(SearchEntryCb_search__changed), browser); - g_signal_connect(browser->search, "stop-search", G_CALLBACK(SearchEntryCb_stop__search), browser); - - /* signals for box container */ - g_signal_connect(browser->box, "key-press-event", G_CALLBACK(boxCb_key_press_event), browser); - - if(old_browser == NULL) webkit_web_view_load_uri(browser->webView, target_url); - - return browser; -} - -/* badwolf_new_tab: Inserts struct Client *browser in GtkNotebook *notebook - * and optionally switches selected tab to it. - * - * returns: - * 0 : Ran successfully - * -1 : Failed to insert a page for browser->box - * -2 : browser is NULL - */ -int -badwolf_new_tab(GtkNotebook *notebook, struct Client *browser, bool auto_switch) -{ - gint current_page = gtk_notebook_get_current_page(notebook); - gchar *title = _("New tab"); - - if(browser == NULL) return -2; - - gtk_widget_show_all(browser->box); - - if(gtk_notebook_insert_page(notebook, browser->box, NULL, (current_page + 1)) == -1) return -1; - - gtk_notebook_set_tab_reorderable(notebook, browser->box, TRUE); - gtk_notebook_set_tab_label(notebook, browser->box, badwolf_new_tab_box(title, browser)); - gtk_notebook_set_menu_label_text(GTK_NOTEBOOK(notebook), browser->box, title); - - gtk_widget_queue_draw(GTK_WIDGET(notebook)); - - if(auto_switch) - { - gtk_notebook_set_current_page(notebook, gtk_notebook_page_num(notebook, browser->box)); - } - - return 0; -} - -static void -new_tabCb_clicked(GtkButton *new_tab, gpointer user_data) -{ - (void)new_tab; - struct Window *window = (struct Window *)user_data; - struct Client *browser = new_browser(window, NULL, NULL); - - badwolf_new_tab(GTK_NOTEBOOK(window->notebook), browser, TRUE); -} - -static void -closeCb_clicked(GtkButton *close, gpointer user_data) -{ - (void)close; - struct Client *browser = (struct Client *)user_data; - - webkit_web_view_try_close(browser->webView); -} - -static void -notebookCb_switch__page(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data) -{ - (void)page_num; - struct Window *window = (struct Window *)user_data; - GtkWidget *label = gtk_notebook_get_tab_label(notebook, page); - - // TODO: Maybe find a better way to store the title - gtk_window_set_title(GTK_WINDOW(window->main_window), gtk_widget_get_tooltip_text(label)); -} - -void -content_managerCb_ready(GObject *store, GAsyncResult *result, gpointer user_data) -{ - (void)store; - struct Window *window = (struct Window *)user_data; - GError *err = NULL; - - WebKitUserContentFilter *filter = - webkit_user_content_filter_store_load_finish(window->content_store, result, &err); - - if(filter == NULL) - { - if(err == NULL) - { - fprintf(stderr, _("badwolf: failed to load content-filter, err: [%d] %s\n"), -1, "unknown"); - } - else - { - fprintf(stderr, - _("badwolf: failed to load content-filter, err: [%d] %s\n"), - err->code, - err->message); - } - } - else - { - fprintf(stderr, _("badwolf: content-filter loaded, adding to content-manager…\n")); - webkit_user_content_manager_add_filter(window->content_manager, filter); - } -} - -static void -storeCb_finish(WebKitUserContentFilterStore *store, GAsyncResult *result, gpointer user_data) -{ - (void)store; - struct Window *window = (struct Window *)user_data; - GError *err = NULL; - - WebKitUserContentFilter *filter = - webkit_user_content_filter_store_save_finish(window->content_store, result, &err); - - if(filter == NULL) - { - if(err == NULL) - { - fprintf(stderr, - _("badwolf: failed to compile content-filters.json, err: [%d] %s\n"), - -1, - "unknown"); - } - else - { - fprintf(stderr, - _("badwolf: failed to compile content-filters.json, err: [%d] %s\n"), - err->code, - err->message); - } - } - else - { - webkit_user_content_filter_store_load( - window->content_store, "a", NULL, content_managerCb_ready, window); - } -} - -void -tray_icon_on_click(GtkStatusIcon *status_icon, gpointer main_window_ptr) -{ - GtkWidget *main_window = GTK_WIDGET(main_window_ptr); - if (gtk_widget_is_visible(main_window)) - gtk_widget_hide(main_window); - else - gtk_widget_show(main_window); -} - -static GtkStatusIcon *create_tray_icon(const struct Window *window) { - GtkStatusIcon *tray_icon; - - tray_icon = gtk_status_icon_new(); - g_signal_connect(G_OBJECT(tray_icon), "activate", G_CALLBACK(tray_icon_on_click), window->main_window); - gtk_status_icon_set_from_icon_name(tray_icon, "badwolf"); - gtk_status_icon_set_tooltip_text(tray_icon, "Badwolf"); - gtk_status_icon_set_visible(tray_icon, TRUE); - - return tray_icon; -} - -int -main(int argc, char *argv[]) -{ - if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'h') { - printf("\ -badwolf [OPTIONS] [URLs]\n\n\ -Options:\n\ --s DD Specifies a custom favicon size, where DD is a two digit number\n\ --nl Tabs won't have a label (page title)\n\ --cl Tabs will have a context label (text that identifies every tab)\n\ --c You won't be able to add or remove any tabs, other than those specified\n\ - as parameters\n\ --t Adds a tray icon. Clicking it toggles visibility of the browser window.\n\ --u All tabs will use an alternative UserAgent\n\ --p Persistent storage, meaning non-session cookies will be stored on drive\n\ --g Separated storage, meaning persistent storage will be done separately for\n\ - each tab context. Doesn't do anything if the -p option isn't selected.\n" - ); - return 0; - } - - struct Window *window = &(struct Window){NULL, NULL, NULL, NULL, NULL, NULL}; - GApplication *application; - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, DATADIR "/locale"); - bind_textdomain_codeset(PACKAGE, "UTF-8"); - textdomain(PACKAGE); - - application = g_application_new("me.hacktivis.badwolf", - G_APPLICATION_HANDLES_COMMAND_LINE | - G_APPLICATION_SEND_ENVIRONMENT | G_APPLICATION_NON_UNIQUE); - g_application_register(application, NULL, NULL); - //g_application_activate(application); - - gtk_init(&argc, &argv); - - fprintf(stderr, _("Running Badwolf version: %s\n"), version); - fprintf(stderr, - _("Buildtime WebKit version: %d.%d.%d\n"), - WEBKIT_MAJOR_VERSION, - WEBKIT_MINOR_VERSION, - WEBKIT_MICRO_VERSION); - fprintf(stderr, - _("Runtime WebKit version: %d.%d.%d\n"), - webkit_get_major_version(), - webkit_get_minor_version(), - webkit_get_micro_version()); - - web_extensions_directory = - 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); - window->downloads_tab = badwolf_downloads_tab_new(); - window->content_manager = webkit_user_content_manager_new(); - - gchar *contentFilterPath = - g_build_filename(g_get_user_config_dir(), g_get_prgname(), "content-filters.json", NULL); - GFile *contentFilterFile = g_file_new_for_path(contentFilterPath); - fprintf(stderr, _("content-filters file set to: %s\n"), contentFilterPath); - - gchar *filtersPath = g_build_filename(g_get_user_cache_dir(), g_get_prgname(), "filters", NULL); - window->content_store = webkit_user_content_filter_store_new(filtersPath); - - webkit_user_content_filter_store_save_from_file(window->content_store, - "a", - contentFilterFile, - NULL, - (GAsyncReadyCallback)storeCb_finish, - window); - - gtk_window_set_default_size( - GTK_WINDOW(window->main_window), BADWOLF_DEFAULT_WIDTH, BADWOLF_DEFAULT_HEIGHT); - gtk_window_set_role(GTK_WINDOW(window->main_window), "browser"); - gtk_window_set_icon_name(GTK_WINDOW(window->main_window), "badwolf"); - - gchar *provider_path_app = g_build_filename(DATADIR, "interface.css", NULL); - /* flawfinder: ignore, just a presence check */ - if(access(provider_path_app, R_OK) == 0) - { - GtkCssProvider *css_provider_app = gtk_css_provider_new(); - gtk_css_provider_load_from_path(css_provider_app, provider_path_app, NULL); - gtk_style_context_add_provider_for_screen( - gtk_widget_get_screen(GTK_WIDGET(window->main_window)), - GTK_STYLE_PROVIDER(css_provider_app), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - } - g_free(provider_path_app); - - gchar *provider_path_user = - g_build_filename(g_get_user_data_dir(), "badwolf", "interface.css", NULL); - /* flawfinder: ignore, just a presence check */ - if(access(provider_path_user, R_OK) == 0) - { - GtkCssProvider *css_provider_user = gtk_css_provider_new(); - gtk_css_provider_load_from_path(css_provider_user, provider_path_user, NULL); - gtk_style_context_add_provider_for_screen( - gtk_widget_get_screen(GTK_WIDGET(window->main_window)), - GTK_STYLE_PROVIDER(css_provider_user), - GTK_STYLE_PROVIDER_PRIORITY_USER); - } - g_free(provider_path_user); - - gtk_widget_set_tooltip_text(window->new_tab, _("Open new tab")); - - gtk_notebook_set_action_widget(GTK_NOTEBOOK(window->notebook), window->new_tab, GTK_PACK_END); - gtk_notebook_set_scrollable(GTK_NOTEBOOK(window->notebook), TRUE); - gtk_notebook_set_tab_pos(GTK_NOTEBOOK(window->notebook), BADWOLF_TAB_POSITION); - gtk_notebook_popup_enable(GTK_NOTEBOOK(window->notebook)); - - gtk_container_add(GTK_CONTAINER(window->main_window), window->notebook); - gtk_widget_queue_draw(window->notebook); - - badwolf_downloads_tab_attach(window); - - g_signal_connect( - window->main_window, "key-press-event", G_CALLBACK(main_windowCb_key_press_event), window); - - g_signal_connect(window->main_window, "destroy", G_CALLBACK(gtk_main_quit), NULL); - g_signal_connect(window->new_tab, "clicked", G_CALLBACK(new_tabCb_clicked), window); - g_signal_connect(window->notebook, "switch-page", G_CALLBACK(notebookCb_switch__page), window); - - while (argc > 1 && argv[1][0] == '-') { - if (argv[1][1] == 'n' && argv[1][2] == 'l') - tabs_no_label = TRUE; - else if (argv[1][1] == 'c' && argv[1][2] == 'l') - tabs_context_label = TRUE; - else if (argv[1][1] == 'c') - tabs_constant = TRUE; - else if (argv[1][1] == 't') - tray_enabled = TRUE; - else if (argv[1][1] == 'u') - alt_useragent = TRUE; - else if (argv[1][1] == 'p') - persistent_storage = TRUE; - else if (argv[1][1] == 'g') - separated_storage = TRUE; - else if (argv[1][1] == 's') { - argv++; - argc--; - custom_favicon_size = (argv[1][0] - '0') * 10 + argv[1][1] - '0'; - } - - argv++; - argc--; - } - - if (!tabs_constant) - gtk_widget_show(window->new_tab); - gtk_widget_show_all(window->main_window); - - if(argc == 1) - badwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, NULL, NULL), FALSE); - else - for(int i = 1; i < argc; ++i) - badwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, argv[i], NULL), TRUE); - - gtk_notebook_set_current_page(GTK_NOTEBOOK(window->notebook), 1); - - if (tray_enabled) - create_tray_icon(window); - - gtk_main(); - - g_object_unref(bookmarks_completion_model); - -#if 0 - /* TRANSLATOR Ignore this entry. Done for forcing Unicode in xgettext. */ - _("ø"); -#endif - - return 0; -} diff --git a/badwolf.desktop b/badwolf.desktop deleted file mode 100644 index 5bf865b..0000000 --- a/badwolf.desktop +++ /dev/null @@ -1,15 +0,0 @@ -# https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/ -[Desktop Entry] -Version=1.1 -Type=Application -Categories=Network;WebBrowser -Comment=A minimalist and privacy-oriented web browser -Comment[fr]=Un navigateur web minimaliste et orienté vers le respect de la vie privée -Exec=badwolf %U -GenericName=Web Browser -GenericName[fr]=Navigateur Web -Icon=badwolf -Keywords=Internet;WWW;Browser;Web;WebKit;WebKitGTK -Keywords[fr]=Internet;WWW;Browser;Web;Surfer;Navigateur;WebKit;WebKitGTK -MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https -Name=Badwolf diff --git a/badwolf.fr.1 b/badwolf.fr.1 deleted file mode 100644 index 7a96a99..0000000 --- a/badwolf.fr.1 +++ /dev/null @@ -1,166 +0,0 @@ -.\" BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser -.\" Copyright © 2019-2022 Badwolf Authors -.\" SPDX-License-Identifier: BSD-3-Clause -.\"******************************************************************* -.\" -.\" This file was generated with po4a. Translate the source file. -.\" -.\"******************************************************************* -.Dd 2022-04-06 -.Dt BADWOLF 1 -.Os -.Sh NAME -.Nm badwolf -.Nd navigateur minimaliste et orienté vie-privée basé sur WebKitGTK -.Sh SYNOPSIS -.Nm -.Op Ar options webkit/gtk -.Op Ar URLs or chemins -.Sh DESCRIPTION -.Nm -est un navigateur minimaliste qui prend soin de la vie privée, c'est -basé WebKitGTK et accept donc les options et variables d'environements de -WebKitGTK et ses dépendances, malheuresement il ne semble pas avoir de pages -de man pour celles-ci. -.Pp -Une configuration dynamique spécifique à -.Nm -sera sans doute rajoutée -dans une version suivante. -.Sh RACCOURCIS -Cette section liste les raccourcis et leurs actions, chaque point est décris -avec le widget actif ou avec -.Aq tout -quand il fonctionne sur la fenêtre -entière, suivit par le raccourcis. -.Bl -tag -width Ds -.It vueweb Ctrl-Défilement -(Dé)-Grossir le zoom de la page. -.It vueweb Ctrl-0 -Remettre le zoom de la page à 100%. -.It tout Ctrl-t -Créer un nouvel onglet (dans une nouvelle session, comme un apuis sur le -bouton dédié) -.It navigateur Ctrl-F4, navigateur Alt-d -Fermer l'onglet courant. -.It navigateur Ctrl-f -Aller dans le champ de recherche. -.It navigateur Ctrl-l -Aller dans la barre d'URL. -.It navigateur Ctrl-Maj-r / Ctrl-r, navigateur F5 -Recharger le contenu dans l'onglet courant (avec/sans nettoyer le cache). -.It navigateur Échap -Arrêter le chargement dans l'onglet courant. -.It navigateur F7 -(Dé)-Activer la navigation par curseur. -.It navigateur F12 -Ouvrir les outils de dévelopement. -.It navigateur Ctrl-[ / Ctrl-] -Naviguer dans l'historique courrant précédent/suivant. -.It navigateur Ctrl-p -Imprimer la page courante. (ouvre une nouvelle fenêtre) -.It tout Alt-Gauche / Alt-Droite -Aller à l'onglet précédent/suivant. -.It tout F1 -Montrer la fenêtre d'À Propos. -.It tout Alt-n -Où n est n'importe quelle touche de la barre numérique. -Aller à l'onglet n, 0 va au dernier. -.El -.Ss PAR DÉFAULTS -Ceci est une liste incomplète des raccourcis par défaults dans WebKit/GTK: -.Bl -tag -width Ds -.It tout Ctrl-PageUp / Ctrl-PageDown -Aller à l'onglet précédent/suivant. -.It recherche Ctrl-g / Ctrl-Maj-g -Quand le champ de recherche est actif, aller au résultat précédent/suivant. -.It recherche Échap -Annule la recherche actuelle. -.El -.Sh ENVIRONMENT -.Bl -tag -width Ds -.It Ev BADWOLF_L10N -Une liste séparé par des deux-points dans le format langue_PAYS où la langue -est en ISO-639 et le PAYS en ISO-3166. -Par example -.Ic BADWOLF_L10N="en_GB:fr_FR:de_DE" . -Quand cette variable n'est pas configuré, la correction orthographique est -désactivée. -Un nom plus générique est voulu pour le futur. -.Pp -Pour avoir la liste des dictionaires installés, executez: -.Ic enchant-lsmod-2 -list-dicts -ou avant enchant 2.0: -.Ic enchant-lsmod -list-dicts -.El -.Sh FICHIERS -Les chemins suivants utilisent la syntaxe de -.Xr sh 1 -pour correctement -supporter la XDG Base Directory Specification, vous pouver utiliser la -commande -.Xr echo 1 -pour vérifier où cela se trouve sur votre système. -.Pp -.Bl -tag -width Ds -compact -.It Pa ${XDG_CONFIG_HOME:-$HOME/.config}/badwolf/content-filters.json -Fichier content-filter spécifique à WebKit, cela permet de blocker le -contenu indésirable (pubs, nagware, …). -Pour une introduction au format, voir (en anglais): -.Lk https://webkit.org/blog/3476/content-blockers-first-look/ -.Lk https://webkit.org/blog/4062/targeting-domains-with-content-blockers/ -.Lk https://developer.apple.com/documentation/safariservices/creating_a_content_blocker -.Pp -Pour un convertiseur de filtres compatibles AdBlockPlus, essayez: -.Lk https://gitlab.com/eyeo/adblockplus/abp2blocklist -.Pp -Pour un fichier prêt à l'usage (que vous devrez mettre à jour -périodiquement), essayez: -.Lk https://easylist-downloads.adblockplus.org/easylist_min_content_blocker.json -.It Pa ${XDG_CACHE_HOME:-$HOME/.cache}/badwolf/filters -Stockage des filtres compilés, les fichiers présents sont automatiquement -générés et ne doivent pas être édité. -Documenté ici seulement pour les isolations ou la gestion des contrôle -d'accès. -.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/bookmarks.xbel -Fichier XBEL (XML Bookmark Exchange Language; Language XML d'Échange de -Marques-Pages), connu pour être supporté par: -.Xr elinks 1 , -.Xr konqueror 1 , -.Xr kbookmarkeditor 1 . Faire un lien symbolique depuisleurs chemins fonctionne mais vous pouvez aussi utiliser des XInclude pour fusionner plusieurs fichiers XBEL. -.Pp -Pour plus d'information à propos du format, voir (en anglais): -.Lk http://pyxml.sourceforge.net/topics/xbel/ -.Pp -Pour un example de fichier XBEL voir: -.Lk https://hacktivis.me/bookmarks.xbel -.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/webkit-web-extension/ -Répertoire contenant les -.Lk https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebExtension.html WebKitWebExtensions -pour être chargés dans -.Nm . Note\ : Ce ne sont pas les Web-Extensions basé sur JavaScript et supporté par Firefox ou Chrome, mais du code natif dans des shared objects qui utilisent l'API WebKitGTK. -.Pp -Des examples de quelques extensions utiles peuvent être trouvés sur: -.Lk https://hacktivis.me/git/badwolf-extensions -.It Pa ${DATADIR:-/usr/local/share}/badwolf/interface.css -.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/interface.css -.\" GNOME can't even into doing any redirections of the few docs available -Fichiers CSS (respectivement système et utilisateur) pour changer le style -de l'interface de -.Nm . -Voir -.Lk http://web.archive.org/web/20210420214617/https://developer.gnome.org/gtk3/stable/chap-css-properties.html -pour la liste des propriétés disponibles. -.Pp -Pour tester les styles je recommende d'utiliser la variable d'environemnt -.Ev GTK_DEBUG=interactive -et d'aller à l'onglet CSS. -.El -.Sh AUTHORS -.An Haelwenn (lanodan) Monnier Aq Mt contact+badwolf@hacktivis.me -.Sh BUGS -Vous pouvez soumettre des contributions ou des tickets à -.Lk https://sr.ht/~lanodan/badwolf/ -avec -.Xr git-send-email 1 -pour les modifications. diff --git a/badwolf.h b/badwolf.h deleted file mode 100644 index f751842..0000000 --- a/badwolf.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef BADWOLF_H_INCLUDED -#define BADWOLF_H_INCLUDED - -#include -#include /* uint64_t */ -#include - -#if !WEBKIT_CHECK_VERSION(2, 32, 0) -#error WebkitGTK 2.32.0 is the latest supported version for badwolf. -#endif - -extern const gchar *homepage; -extern const gchar *version; - -struct Window -{ - GtkWidget *main_window; - GtkWidget *notebook; - GtkWidget *new_tab; - GtkWidget *downloads_tab; - WebKitUserContentManager *content_manager; - WebKitUserContentFilterStore *content_store; -}; - -struct Client -{ - GtkWidget *box; - - GtkWidget *toolbar; - GtkWidget *back; - GtkWidget *forward; - GtkWidget *javascript; - GtkWidget *auto_load_images; - GtkWidget *location; - - uint64_t context_id; - WebKitWebView *webView; - struct Window *window; - - GtkWidget *statusbar; - GtkWidget *statuslabel; - GtkWidget *search; -}; - -GtkWidget *badwolf_new_tab_box(const gchar *title, struct Client *browser); -void webView_tab_label_change(struct Client *browser, const gchar *title); -struct Client * -new_browser(struct Window *window, const gchar *target_url, struct Client *old_browser); -int badwolf_new_tab(GtkNotebook *notebook, struct Client *browser, bool auto_switch); -gint badwolf_get_tab_position(GtkContainer *notebook, GtkWidget *child); -#endif /* BADWOLF_H_INCLUDED */ diff --git a/badwolf.inkscape.svg b/badwolf.inkscape.svg deleted file mode 100644 index b28266a..0000000 --- a/badwolf.inkscape.svg +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/badwolf.svg b/badwolf.svg deleted file mode 100644 index bbf3777..0000000 --- a/badwolf.svg +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bookmarks.c b/bookmarks.c index 2a772cc..d662236 100644 --- a/bookmarks.c +++ b/bookmarks.c @@ -1,6 +1,6 @@ #include "bookmarks.h" -#include "badwolf.h" +#include "goodwolf.h" #include "config.h" #include /* _() and other internationalization/localization helpers */ @@ -37,7 +37,7 @@ bookmarks_completion_setup(GtkEntryCompletion *location_completion, GtkTreeModel 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); + gtk_entry_completion_set_inline_selection(location_completion, GOODWOLF_LOCATION_INLINE_SELECTION); } static void @@ -74,7 +74,7 @@ bookmarks_completion_init() xmlXPathObjectPtr xpathObj = NULL; const xmlChar *xpathExpr = (const xmlChar *)"//bookmark/@href"; - char *filename = g_build_filename(g_get_user_data_dir(), "badwolf", "bookmarks.xbel", NULL); + char *filename = g_build_filename(g_get_user_data_dir(), "goodwolf", "bookmarks.xbel", NULL); GtkListStore *list_store = gtk_list_store_new(1, G_TYPE_STRING); /* flawfinder: ignore, just a presence check */ diff --git a/bookmarks_test.fixtures/full/badwolf/bookmarks.xbel b/bookmarks_test.fixtures/full/badwolf/bookmarks.xbel deleted file mode 100644 index 192cfb2..0000000 --- a/bookmarks_test.fixtures/full/badwolf/bookmarks.xbel +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Operating Systems - - 9Front - Fork of Plan 9, a Unix successor by Bell Labs - - - LitePubProfile of ActivityPub used by Pleroma et al. - - diff --git a/bookmarks_test.fixtures/full/goodwolf/bookmarks.xbel b/bookmarks_test.fixtures/full/goodwolf/bookmarks.xbel new file mode 100644 index 0000000..192cfb2 --- /dev/null +++ b/bookmarks_test.fixtures/full/goodwolf/bookmarks.xbel @@ -0,0 +1,16 @@ + + + + + + + Operating Systems + + 9Front + Fork of Plan 9, a Unix successor by Bell Labs + + + LitePubProfile of ActivityPub used by Pleroma et al. + + diff --git a/config.h b/config.h index 6bd76df..8b82a1b 100644 --- a/config.h +++ b/config.h @@ -1,6 +1,6 @@ #ifndef CONFIG_H_INCLUDED #define CONFIG_H_INCLUDED -/* BADWOLF_TAB_POSITION: Position of the tab listing, can be one of: +/* GOODWOLF_TAB_POSITION: Position of the tab listing, can be one of: * - GTK_POS_TOP * - GTK_POS_BOTTOM * - GTK_POS_RIGHT @@ -8,22 +8,22 @@ * * See https://developer.gnome.org/gtk3/stable/gtk3-Standard-Enumerations.html#GtkPositionType */ -#define BADWOLF_TAB_POSITION GTK_POS_TOP +#define GOODWOLF_TAB_POSITION GTK_POS_TOP -/* BADWOLF_TAB_LABEL_CHARWIDTH: Amount of characters the tab label text fits - * Quite conflicts with BADWOLF_TAB_BOX_WIDTH, recommended to only define one +/* GOODWOLF_TAB_LABEL_CHARWIDTH: Amount of characters the tab label text fits + * Quite conflicts with GOODWOLF_TAB_BOX_WIDTH, recommended to only define one */ -#define BADWOLF_TAB_LABEL_CHARWIDTH 26 +#define GOODWOLF_TAB_LABEL_CHARWIDTH 26 -/* BADWOLF_TAB_BOX_WIDTH: Requested width (in pixels) for the whole tab - * Quite conflicts with BADWOLF_TAB_LABEL_CHARWIDTH, recommended to only define one +/* GOODWOLF_TAB_BOX_WIDTH: Requested width (in pixels) for the whole tab + * Quite conflicts with GOODWOLF_TAB_LABEL_CHARWIDTH, recommended to only define one */ -//#define BADWOLF_TAB_BOX_WIDTH 120 +//#define GOODWOLF_TAB_BOX_WIDTH 120 -// BADWOLF_TAB_HEXPAND: Should the tab try to fill the available horizontal space? -#define BADWOLF_TAB_HEXPAND FALSE +// GOODWOLF_TAB_HEXPAND: Should the tab try to fill the available horizontal space? +#define GOODWOLF_TAB_HEXPAND FALSE -/* BADWOLF_TAB_LABEL_ELLIPSIZE: pango ellipsize mode of the tab label text, can be one of: +/* GOODWOLF_TAB_LABEL_ELLIPSIZE: pango ellipsize mode of the tab label text, can be one of: * - PANGO_ELLIPSIZE_NONE * - PANGO_ELLIPSIZE_START * - PANGO_ELLIPSIZE_MIDDLE @@ -31,40 +31,40 @@ * * See https://developer.gnome.org/pango/stable/pango-Layout-Objects.html#PangoEllipsizeMode */ -#define BADWOLF_TAB_LABEL_ELLIPSIZE PANGO_ELLIPSIZE_MIDDLE +#define GOODWOLF_TAB_LABEL_ELLIPSIZE PANGO_ELLIPSIZE_MIDDLE -// BADWOLF_BOX_PADDING: Amount of padding between browser’s box (tab child) elements -#define BADWOLF_BOX_PADDING 0 +// GOODWOLF_BOX_PADDING: Amount of padding between browser’s box (tab child) elements +#define GOODWOLF_BOX_PADDING 0 -// BADWOLF_TOOLBAR_PADDING: Amount of padding between toolbar elements -#define BADWOLF_TOOLBAR_PADDING 0 +// GOODWOLF_TOOLBAR_PADDING: Amount of padding between toolbar elements +#define GOODWOLF_TOOLBAR_PADDING 0 -// BADWOLF_TOOLBAR_PADDING: Amount of padding between toolbar elements -#define BADWOLF_TOOLBAR_SEPARATOR_PADDING 4 +// GOODWOLF_TOOLBAR_PADDING: Amount of padding between toolbar elements +#define GOODWOLF_TOOLBAR_SEPARATOR_PADDING 4 -// BADWOLF_STATUSBAR_PADDING: Amount of padding between statusbar elements -#define BADWOLF_STATUSBAR_PADDING 0 +// GOODWOLF_STATUSBAR_PADDING: Amount of padding between statusbar elements +#define GOODWOLF_STATUSBAR_PADDING 0 -// BADWOLF_DOWNLOAD_PADDING: Amount of padding between download list row-elements -#define BADWOLF_DOWNLOAD_PADDING 5 +// GOODWOLF_DOWNLOAD_PADDING: Amount of padding between download list row-elements +#define GOODWOLF_DOWNLOAD_PADDING 5 -/* BADWOLF_DEFAULT_WIDTH / BADWOLF_DEFAULT_HEIGHT: +/* GOODWOLF_DEFAULT_WIDTH / GOODWOLF_DEFAULT_HEIGHT: * Used to define the default width/height of the window, * useful for floating Window Managers, probably useless in tiling ones * * See https://developer.gnome.org/gtk3/stable/GtkWindow.html#gtk-window-set-default-size */ -#define BADWOLF_DEFAULT_WIDTH 800 -#define BADWOLF_DEFAULT_HEIGHT 600 +#define GOODWOLF_DEFAULT_WIDTH 800 +#define GOODWOLF_DEFAULT_HEIGHT 600 -/* BADWOLF_WEBKIT_SETTINGS: +/* GOODWOLF_WEBKIT_SETTINGS: * Used when creating a new view with webkit_settings_new_with_settings the usage is: * setting-name, setting-value, setting-name, …, NULL * * See: https://webkitgtk.org/reference/webkit2gtk/stable/WebKitSettings.html */ // clang-format off -#define BADWOLF_WEBKIT_SETTINGS \ +#define GOODWOLF_WEBKIT_SETTINGS \ "default-charset", "utf-8", \ "enable-accelerated-2d-canvas", FALSE, \ "enable-caret-browsing", FALSE, \ @@ -83,7 +83,7 @@ NULL // clang-format on -/* BADWOLF_STATUSLABEL_ELLIPSIZE: pango ellipsize mode of the status bar label text, can be one of: +/* GOODWOLF_STATUSLABEL_ELLIPSIZE: pango ellipsize mode of the status bar label text, can be one of: * - PANGO_ELLIPSIZE_NONE * - PANGO_ELLIPSIZE_START * - PANGO_ELLIPSIZE_MIDDLE @@ -91,9 +91,9 @@ * * See https://developer.gnome.org/pango/stable/pango-Layout-Objects.html#PangoEllipsizeMode */ -#define BADWOLF_STATUSLABEL_ELLIPSIZE PANGO_ELLIPSIZE_MIDDLE +#define GOODWOLF_STATUSLABEL_ELLIPSIZE PANGO_ELLIPSIZE_MIDDLE -/* BADWOLF_DOWNLOAD_FILE_PATH_ELLIPSIZE: pango ellipsize mode of the download destination path, +/* GOODWOLF_DOWNLOAD_FILE_PATH_ELLIPSIZE: pango ellipsize mode of the download destination path, * can be one of: * - PANGO_ELLIPSIZE_NONE * - PANGO_ELLIPSIZE_START @@ -102,9 +102,9 @@ * * See https://developer.gnome.org/pango/stable/pango-Layout-Objects.html#PangoEllipsizeMode */ -#define BADWOLF_DOWNLOAD_FILE_PATH_ELLIPSIZE PANGO_ELLIPSIZE_MIDDLE +#define GOODWOLF_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 +// GOODWOLF_LOCATION_INLINE_SELECTION: show selected completion as a selection in location entry +#define GOODWOLF_LOCATION_INLINE_SELECTION TRUE #endif /* CONFIG_H_INCLUDED */ diff --git a/configure b/configure index ef8c473..54fc25c 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #!/bin/sh VERSION=1.2.0 VERSION_FULL=${VERSION}$(./version.sh) -ICON_SIZES="$(for i in 24 32 48 64 128 256; do printf 'icons/hicolor/%sx%s/apps/badwolf.png ' $i $i ; done)" +ICON_SIZES="$(for i in 24 32 48 64 128 256; do printf 'icons/hicolor/%sx%s/apps/goodwolf.png ' $i $i ; done)" DEPS="gtk+-3.0 libxml-2.0" min_webkitgtk=2.32.0 @@ -103,8 +103,8 @@ done # Fallback definitions for dirs, based on $PREFIX BINDIR="${BINDIR:-${PREFIX}/bin}" MANDIR="${MANDIR:-${PREFIX}/share/man}" -DOCDIR="${DOCDIR:-${PREFIX}/share/doc/badwolf-${VERSION}}" -DATADIR="${DATADIR:-${PREFIX}/share/badwolf}" +DOCDIR="${DOCDIR:-${PREFIX}/share/doc/goodwolf-${VERSION}}" +DATADIR="${DATADIR:-${PREFIX}/share/goodwolf}" APPSDIR="${APPSDIR:-${PREFIX}/share/applications}" # Add some extra CFLAGS diff --git a/downloads.c b/downloads.c index 707505f..098282b 100644 --- a/downloads.c +++ b/downloads.c @@ -4,7 +4,7 @@ #include "downloads.h" -#include "badwolf.h" +#include "goodwolf.h" #include "config.h" #include /* _() and other internationalization/localization helpers */ @@ -37,7 +37,7 @@ void download_new_entry(WebKitDownload *webkit_download, struct Download *download) { download->error = 0; - download->container = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, BADWOLF_DOWNLOAD_PADDING); + download->container = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, GOODWOLF_DOWNLOAD_PADDING); download->progress = gtk_progress_bar_new(); download->file_path = gtk_label_new(NULL); download->status = gtk_label_new(_("Download starting…")); @@ -46,7 +46,7 @@ download_new_entry(WebKitDownload *webkit_download, struct Download *download) download->stop_icon = gtk_button_new_from_icon_name("process-stop", GTK_ICON_SIZE_SMALL_TOOLBAR); gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(download->progress), TRUE); - gtk_label_set_ellipsize(GTK_LABEL(download->file_path), BADWOLF_DOWNLOAD_FILE_PATH_ELLIPSIZE); + gtk_label_set_ellipsize(GTK_LABEL(download->file_path), GOODWOLF_DOWNLOAD_FILE_PATH_ELLIPSIZE); g_signal_connect( download->stop_icon, "clicked", G_CALLBACK(download_stop_iconCb_clicked), webkit_download); @@ -182,13 +182,13 @@ downloadCb_received_data(WebKitDownload *webkit_download, guint64 data_lenght, g } GtkWidget * -badwolf_downloads_tab_new() +goodwolf_downloads_tab_new() { return gtk_list_box_new(); } void -badwolf_downloads_tab_attach(struct Window *window) +goodwolf_downloads_tab_attach(struct Window *window) { GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); gtk_widget_set_name(scrolled_window, "browser__scrollwin_downloads"); @@ -202,7 +202,7 @@ badwolf_downloads_tab_attach(struct Window *window) GtkWidget *icon = gtk_image_new_from_icon_name("emblem-downloads", GTK_ICON_SIZE_SMALL_TOOLBAR); gtk_widget_set_name(icon, "browser__tabbox__icon"); - gtk_widget_set_hexpand(tab_box, BADWOLF_TAB_HEXPAND); + gtk_widget_set_hexpand(tab_box, GOODWOLF_TAB_HEXPAND); gtk_box_pack_start(GTK_BOX(tab_box), icon, FALSE, FALSE, 0); diff --git a/downloads.h b/downloads.h index fa5513e..5c34009 100644 --- a/downloads.h +++ b/downloads.h @@ -1,4 +1,4 @@ -#include "badwolf.h" +#include "goodwolf.h" #include @@ -24,5 +24,5 @@ gboolean downloadCb_decide_destination(WebKitDownload *download, void downloadCb_failed(WebKitDownload *webkit_download, GError *error, gpointer user_data); void downloadCb_finished(WebKitDownload *download, gpointer user_data); void downloadCb_received_data(WebKitDownload *download, guint64 data_lenght, gpointer user_data); -GtkWidget *badwolf_downloads_tab_new(); -void badwolf_downloads_tab_attach(struct Window *window); +GtkWidget *goodwolf_downloads_tab_new(); +void goodwolf_downloads_tab_attach(struct Window *window); diff --git a/fmt.c b/fmt.c index 0c47e00..44cd3df 100644 --- a/fmt.c +++ b/fmt.c @@ -10,12 +10,12 @@ void fmt_context_id(uint64_t num, char *out, int withSeparator) { /* flawfinder: ignore. bound checks are done */ - char buf[BADWOLF_CTX_SIZ] = {0, 0, 0, 0, 0, 0, 0}; + char buf[GOODWOLF_CTX_SIZ] = {0, 0, 0, 0, 0, 0, 0}; int len = 2; buf[++len] = alpha_digits[num % 26]; num /= 26; - while(num > 0 && len < (BADWOLF_CTX_SIZ - 1)) + while(num > 0 && len < (GOODWOLF_CTX_SIZ - 1)) { buf[++len] = alpha_digits[(num - 1) % 26]; num /= 26; diff --git a/fmt.h b/fmt.h index 06a13df..b8695cd 100644 --- a/fmt.h +++ b/fmt.h @@ -1,4 +1,4 @@ #include // uint64_t -#define BADWOLF_CTX_SIZ 7 +#define GOODWOLF_CTX_SIZ 7 void fmt_context_id(uint64_t num, char *out, int withSeparator); diff --git a/goodwolf.1 b/goodwolf.1 new file mode 100644 index 0000000..2a4445e --- /dev/null +++ b/goodwolf.1 @@ -0,0 +1,147 @@ +.\" BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser +.\" Copyright © 2019-2022 Badwolf Authors +.\" SPDX-License-Identifier: BSD-3-Clause +.Dd 2022-04-06 +.Dt GOODWOLF 1 +.Os +.Sh NAME +.Nm goodwolf +.Nd minimalist and privacy-oriented web browser based on WebKitGTK +.Sh SYNOPSIS +.Nm +.Op Ar webkit/gtk options +.Op Ar URLs or paths +.Sh DESCRIPTION +.Nm +is a minimalist browser that cares about privacy, it is based on WebKitGTK and thus also accepts WebKitGTK (and dependencies) flags and environment variables, unfortunately there doesn't seems to be manpages for theses. +.Pp +Runtime configuration specific to +.Nm +will probably get added at a later release. +.Sh KEYBINDINGS +The following section lists the keybinding by their action, each item is described by the widget the focus is on or +.Aq any +if it works for the whole window, followed by the keybind it grabs. +.Bl -tag -width Ds +.It webview Ctrl-Scroll +Zooms the webpage in/out. +.It webview Ctrl-0 +Resets webpage zoom to 100%. +.It any Ctrl-t +Creates a new tab (in a new session, similar as pressing the button) +.It browser Ctrl-F4, browser Alt-d +Closes the current tab +.It browser Ctrl-f +Focuses on the search entry +.It browser Ctrl-l +Focuses on the location(URL) entry +.It browser Ctrl-Shift-r / Ctrl-r, browser F5 +Reloads the content in the current tab (with/without clearing cache) +.It browser Escape +Stops loading the content in the current tab +.It browser F7 +Toggles caret browsing. +.It browser F12 +Opens the web inspector. +.It browser Ctrl-[ / Ctrl-] +Go back/forward in current tab's history +.It browser Ctrl-p +Print the current page. (spawns a dialog) +.It any Alt-Left / Alt-Right +Go to the previous/next tab +.It any F1 +Shows the about dialog +.It any Alt-n +Where n is any numeric-row key. +Go to the n-th tab, 0 goes to the last one. +.El +.Ss DEFAULT ONES +Here is a incomplete list of the default Webkit/GTK keybindings: +.Bl -tag -width Ds +.It any Ctrl-PageUp / Ctrl-PageDown +Go to the previous/next tab +.It search Ctrl-g / Ctrl-Shift-g +When the search box is focused it goes to the Next/Previous search term. +.It search Escape +Cancels current search +.El +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev GOODWOLF_L10N +A colon-separated list in the form lang_COUNTRY where lang is in ISO-639 and COUNTRY in ISO-3166. +For example +.Ic GOODWOLF_L10N="en_GB:fr_FR:de_DE" . +When this variable isn't set, spelling isn't activated. +A more generic variable name is also intended to be used in the future. +.Pp +To get the list of supported dictionaries execute +.Ic enchant-lsmod-2 -list-dicts +or before enchant 2.0: +.Ic enchant-lsmod -list-dicts +.El +.Sh FILES +The following paths are using +.Xr sh 1 +syntax to correctly support XDG Base Directory Specification, you can use the +.Xr echo 1 +command to check where it is on your system. +.Pp +.Bl -tag -width Ds -compact +.It Pa ${XDG_CONFIG_HOME:-$HOME/.config}/goodwolf/content-filters.json +WebKit-specific content-filter file, this allows to block unwanted content (ads, nagware, ...). +For some introductory information about the format see: +.Lk https://webkit.org/blog/3476/content-blockers-first-look/ +.Lk https://webkit.org/blog/4062/targeting-domains-with-content-blockers/ +.Lk https://developer.apple.com/documentation/safariservices/creating_a_content_blocker +.Pp +For a converter using AblockPlus-style filters, try: +.Lk https://gitlab.com/eyeo/adblockplus/abp2blocklist +.Pp +For a ready-to-use file (that you should update periodically), try: +.Lk https://easylist-downloads.adblockplus.org/easylist_min_content_blocker.json +.It Pa ${XDG_CACHE_HOME:-$HOME/.cache}/goodwolf/filters +This is where the compiled filters are stored, the file(s) in it are automatically generated and so shouldn't be edited. +Documented here only for sandboxing / access-control purposes. +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/goodwolf/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 but you might also want to use XInclude to merge multiple XBEL files. +.Pp +For more information about this format see: +.Lk http://pyxml.sourceforge.net/topics/xbel/ +.Pp +For an example XBEL file see: +.Lk https://hacktivis.me/bookmarks.xbel +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/goodwolf/webkit-web-extension/ +Directory containing the +.Lk https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebExtension.html WebKitWebExtensions +to be loaded into +.Nm . Note: They aren't the JavaScript-based Web-Extensions supported by Firefox or Chrome, but native code in shared objects using the WebKitGTK API. +.Pp +Examples of useful extensions may be found at: +.Lk https://hacktivis.me/git/goodwolf-extensions +.It Pa ${DATADIR:-/usr/local/share}/goodwolf/interface.css +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/goodwolf/interface.css +CSS files (respectively system and user-level) for styling +.Nm +interface. +See +.\" GNOME can't even into doing any redirections of the few docs available +.Lk http://web.archive.org/web/20210420214617/https://developer.gnome.org/gtk3/stable/chap-css-properties.html +for the properties being available. +.Pp +For testing your styles I would recommend using the +.Ev GTK_DEBUG=interactive +environment variable on launching +.Nm +and going to the CSS tab. +.El +.Sh AUTHORS +.An Haelwenn (lanodan) Monnier Aq Mt contact+goodwolf@hacktivis.me +.Sh BUGS +You can submit contributions or tickets to +.Lk https://sr.ht/~lanodan/goodwolf/ +with +.Xr git-send-email 1 +for patches. diff --git a/goodwolf.c b/goodwolf.c new file mode 100644 index 0000000..cb0b1b2 --- /dev/null +++ b/goodwolf.c @@ -0,0 +1,1329 @@ +// BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser +// Copyright © 2019-2021 Badwolf Authors +// SPDX-License-Identifier: BSD-3-Clause + +#include "goodwolf.h" + +#include "bookmarks.h" +#include "config.h" +#include "downloads.h" +#include "fmt.h" +#include "keybindings.h" +#include "uri.h" + +#include +#include /* _() and other internationalization/localization helpers */ +#include /* soup* */ +#include /* LC_* */ +#include /* perror(), fprintf(), snprintf() */ +#include /* malloc() */ +#include /* access() */ + +const gchar *homepage = "https://hacktivis.me/projects/goodwolf"; +const gchar *version = VERSION; + +static gchar *web_extensions_directory; +static uint64_t context_id_counter = 0; +GtkTreeModel *bookmarks_completion_model; + +static gboolean tabs_no_label = false; +static gboolean tabs_constant = false; +static gboolean tabs_context_label = false; +static gboolean tray_enabled = false; +static gboolean alt_useragent = false; +static int custom_favicon_size = 30; +static gboolean persistent_storage = false; +static gboolean separated_storage = false; + +static gboolean WebViewCb_close(WebKitWebView *webView, gpointer user_data); +static gboolean WebViewCb_web_process_terminated(WebKitWebView *webView, + WebKitWebProcessTerminationReason reason, + gpointer user_data); +static gboolean +WebViewCb_notify__uri(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); +static gboolean +WebViewCb_notify__title(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); +static gboolean +WebViewCb_notify__favicon(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); +static gboolean +WebViewCb_notify__is__playing__audio(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); +static gboolean WebViewCb_notify__estimated_load_progress(WebKitWebView *webView, + GParamSpec *pspec, + gpointer user_data); +static gboolean WebViewCb_mouse_target_changed(WebKitWebView *webView, + WebKitHitTestResult *hit, + guint modifiers, + gpointer user_data); +static WebKitWebView *WebViewCb_create(WebKitWebView *related_web_view, + WebKitNavigationAction *navigation_action, + gpointer user_data); +static gboolean WebViewCb_permission_request(WebKitWebView *web_view, + WebKitPermissionRequest *request, + gpointer user_data); +static gboolean WebViewCb_decide_policy(WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType decision_type, + gpointer user_data); +static void +WebViewCb_load_changed(WebKitWebView *webView, WebKitLoadEvent load_event, gpointer user_data); +static void web_contextCb_download_started(WebKitWebContext *web_context, + WebKitDownload *download, + gpointer user_data); +static gboolean locationCb_activate(GtkEntry *location, gpointer user_data); +static gboolean javascriptCb_toggled(GtkButton *javascript, gpointer user_data); +static gboolean auto_load_imagesCb_toggled(GtkButton *auto_load_images, gpointer user_data); +static void backCb_clicked(GtkButton *back, gpointer user_data); +static void forwardCb_clicked(GtkButton *forward, gpointer user_data); +static void printCb_clicked(GtkButton *forward, gpointer user_data); +static gboolean SearchEntryCb_next__match(GtkSearchEntry *search, gpointer user_data); +static gboolean SearchEntryCb_previous__match(GtkSearchEntry *search, gpointer user_data); +static gboolean SearchEntryCb_search__changed(GtkSearchEntry *search, gpointer user_data); +static gboolean SearchEntryCb_stop__search(GtkSearchEntry *search, gpointer user_data); +static void new_tabCb_clicked(GtkButton *new_tab, gpointer user_data); +static void closeCb_clicked(GtkButton *close, gpointer user_data); +static void +notebookCb_switch__page(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data); +void content_managerCb_ready(GObject *store, GAsyncResult *result, gpointer user_data); + +static gboolean +WebViewCb_close(WebKitWebView *webView, gpointer user_data) +{ + (void)webView; + struct Client *browser = (struct Client *)user_data; + + gtk_widget_destroy(browser->box); + + free(browser); + + return TRUE; +} + +static gboolean +WebViewCb_web_process_terminated(WebKitWebView *webView, + WebKitWebProcessTerminationReason reason, + gpointer user_data) +{ + (void)webView; + struct Client *browser = (struct Client *)user_data; + + switch(reason) + { + case WEBKIT_WEB_PROCESS_CRASHED: + fprintf(stderr, "%s", _("the web process crashed.\n")); + webView_tab_label_change(browser, _("Crashed")); + break; + case WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT: + fprintf(stderr, "%s", _("the web process exceeded the memory limit.\n")); + webView_tab_label_change(browser, _("Out of Memory")); + break; + default: + fprintf(stderr, "%s", _("the web process terminated for an unknown reason.\n")); + webView_tab_label_change(browser, _("Unknown Crash")); + } + + return FALSE; +} + +static gboolean +WebViewCb_notify__uri(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data) +{ + (void)webView; + (void)pspec; + const gchar *location_uri; + struct Client *browser = (struct Client *)user_data; + + location_uri = webkit_web_view_get_uri(browser->webView); + + gtk_entry_set_text(GTK_ENTRY(browser->location), location_uri); + + if(webkit_uri_for_display(location_uri) != location_uri) + gtk_widget_set_tooltip_text(browser->location, webkit_uri_for_display(location_uri)); + else + gtk_widget_set_has_tooltip(browser->location, false); + + return TRUE; +} + +cairo_surface_t* scale_favicon(cairo_surface_t *f) +{ + if (f == NULL) return NULL; + gint pixel_size = custom_favicon_size; + if (pixel_size == 0) { + gtk_icon_size_lookup(GTK_ICON_SIZE_SMALL_TOOLBAR, NULL, &pixel_size); + if (pixel_size == 0) return NULL; + } + + cairo_surface_t *result = cairo_surface_create_similar(f, + cairo_surface_get_content(f), + pixel_size, + pixel_size); + cairo_t *cr = cairo_create(result); + cairo_scale(cr, + (double)pixel_size/cairo_image_surface_get_width(f), + (double)pixel_size/cairo_image_surface_get_height(f)); + cairo_set_source_surface(cr, f, 0, 0); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + cairo_destroy(cr); + return result; +} + +GtkWidget * +goodwolf_new_tab_box(const gchar *title, struct Client *browser) +{ + (void)browser; + /* flawfinder: ignore. bound checks are done */ + char context_id_str[GOODWOLF_CTX_SIZ] = {0, 0, 0, 0, 0, 0, 0}; + + fmt_context_id(browser->context_id, context_id_str, 1); + + GtkWidget *tab_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(tab_box, "browser__tabbox"); + + GtkWidget *close = + gtk_button_new_from_icon_name("window-close-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_widget_set_name(close, "browser__tabbox__close"); + GtkWidget *context_label; + GtkWidget *context_label_event_box; + if (tabs_context_label) { + context_label = gtk_label_new(context_id_str); + gtk_widget_set_name(context_label, "browser__tabbox__context_label"); + context_label_event_box = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(context_label_event_box), context_label); + } + GtkWidget *favicon = + gtk_image_new_from_surface(scale_favicon(webkit_web_view_get_favicon(browser->webView))); + gtk_widget_set_name(favicon, "browser__tabbox__favicon"); + GtkWidget *favicon_event_box = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(favicon_event_box), favicon); + GtkWidget *label = gtk_label_new(title); + gtk_widget_set_name(label, "browser__tabbox__label"); + GtkWidget *label_event_box = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(label_event_box), label); + GtkWidget *playing = + gtk_image_new_from_icon_name("audio-volume-high-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_widget_set_name(playing, "browser__tabbox__playing"); + GtkWidget *playing_event_box = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(playing_event_box), playing); + +#ifdef GOODWOLF_TAB_BOX_WIDTH + gtk_widget_set_size_request(label, GOODWOLF_TAB_BOX_WIDTH, -1); +#endif +#ifdef GOODWOLF_TAB_LABEL_CHARWIDTH + gtk_label_set_width_chars(GTK_LABEL(label), GOODWOLF_TAB_LABEL_CHARWIDTH); +#endif + gtk_widget_set_hexpand(tab_box, GOODWOLF_TAB_HEXPAND); + + gtk_label_set_ellipsize(GTK_LABEL(label), GOODWOLF_TAB_LABEL_ELLIPSIZE); + gtk_label_set_single_line_mode(GTK_LABEL(label), TRUE); + + if (tabs_context_label) { + gtk_label_set_single_line_mode(GTK_LABEL(context_label), TRUE); + gtk_box_pack_start(GTK_BOX(tab_box), context_label_event_box, TRUE, TRUE, 0); + } + + gtk_box_pack_start(GTK_BOX(tab_box), favicon_event_box, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(tab_box), playing_event_box, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(tab_box), label_event_box, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(tab_box), close, FALSE, FALSE, 0); + + gtk_button_set_relief(GTK_BUTTON(close), GTK_RELIEF_NONE); + + g_signal_connect(close, "clicked", G_CALLBACK(closeCb_clicked), browser); + + gtk_widget_set_tooltip_text(tab_box, title); + + gtk_widget_show_all(tab_box); + gtk_widget_set_visible(playing, webkit_web_view_is_playing_audio(browser->webView)); + gtk_widget_set_visible(label, !tabs_no_label); + gtk_widget_set_visible(close, !tabs_constant); + gtk_widget_set_events(label, GDK_BUTTON_RELEASE_MASK); + g_signal_connect( + tab_box, "button-release-event", G_CALLBACK(tab_boxCb_button_release_event), browser); + + return tab_box; +} + +static gboolean +WebViewCb_notify__title(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data) +{ + (void)webView; + (void)pspec; + struct Client *browser = (struct Client *)user_data; + + webView_tab_label_change(browser, NULL); + + return TRUE; +} + +static gboolean +WebViewCb_notify__is__playing__audio(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data) +{ + (void)webView; + (void)pspec; + struct Client *browser = (struct Client *)user_data; + + webView_tab_label_change(browser, NULL); + + return TRUE; +} + +static gboolean +WebViewCb_notify__favicon(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data) +{ + (void)webView; + (void)pspec; + struct Client *browser = (struct Client *)user_data; + + webView_tab_label_change(browser, NULL); + + return TRUE; +} + +void +webView_tab_label_change(struct Client *browser, const gchar *title) +{ + GtkWidget *notebook = browser->window->notebook; + +#define title_IS_EMPTY (title == NULL) || strnlen(title, 2) == 0 + + if(title_IS_EMPTY) title = webkit_web_view_get_title(browser->webView); + if(title_IS_EMPTY) title = webkit_web_view_get_uri(browser->webView); + if(title_IS_EMPTY) title = "BadWolf"; + + gtk_notebook_set_tab_label( + GTK_NOTEBOOK(notebook), browser->box, goodwolf_new_tab_box(title, browser)); + gtk_notebook_set_menu_label_text(GTK_NOTEBOOK(notebook), browser->box, title); + + // Set the window title if the title change was on the current tab + if(gtk_notebook_page_num(GTK_NOTEBOOK(notebook), browser->box) == + gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))) + gtk_window_set_title(GTK_WINDOW(browser->window->main_window), title); +} + +static gboolean +WebViewCb_notify__estimated_load_progress(WebKitWebView *webView, + GParamSpec *pspec, + gpointer user_data) +{ + (void)webView; + (void)pspec; + struct Client *browser = (struct Client *)user_data; + gdouble progress; + + progress = webkit_web_view_get_estimated_load_progress(browser->webView); + + if(progress >= 1) progress = 0; + + gtk_entry_set_progress_fraction(GTK_ENTRY(browser->location), progress); + + return TRUE; +} + +static gboolean +WebViewCb_mouse_target_changed(WebKitWebView *webView, + WebKitHitTestResult *hit, + guint modifiers, + gpointer user_data) +{ + (void)webView; + (void)modifiers; + struct Client *browser = (struct Client *)user_data; + + if(webkit_hit_test_result_context_is_link(hit)) + { + const gchar *link_uri = webkit_hit_test_result_get_link_uri(hit); + + gtk_label_set_text(GTK_LABEL(browser->statuslabel), webkit_uri_for_display(link_uri)); + } + else + gtk_label_set_text(GTK_LABEL(browser->statuslabel), NULL); + + return FALSE; +} + +static gboolean +WebViewCb_scroll_event(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + (void)widget; + struct Client *browser = (struct Client *)data; + gdouble delta_x, delta_y; + gdouble zoom; + + if(((GdkEventScroll *)event)->state & GDK_CONTROL_MASK) + { + gdk_event_get_scroll_deltas(event, &delta_x, &delta_y); + zoom = webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(browser->webView)); + zoom -= delta_y * 0.1; + webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(browser->webView), zoom); + return TRUE; + } + + return FALSE; +} + +static WebKitWebView * +WebViewCb_create(WebKitWebView *related_web_view, + WebKitNavigationAction *navigation_action, + gpointer user_data) +{ + (void)navigation_action; + struct Client *old_browser = (struct Client *)user_data; + struct Client *browser = NULL; + + // shouldn't be needed but better be safe + old_browser->webView = related_web_view; + + browser = new_browser(old_browser->window, NULL, old_browser); + + if(goodwolf_new_tab(GTK_NOTEBOOK(old_browser->window->notebook), browser, FALSE) < 0) + return NULL; + else + return browser->webView; +} + +static gboolean +WebViewCb_permission_request(WebKitWebView *web_view, + WebKitPermissionRequest *request, + gpointer user_data) +{ + (void)web_view; + (void)user_data; + + webkit_permission_request_deny(request); + + return TRUE; /* Stop other handlers */ +} + +static gboolean +WebViewCb_decide_policy(WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType decision_type, + gpointer user_data) +{ + WebKitResponsePolicyDecision *r; + (void)web_view; + (void)user_data; + + switch(decision_type) + { + case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: + r = WEBKIT_RESPONSE_POLICY_DECISION(decision); + if(!webkit_response_policy_decision_is_mime_type_supported(r)) + webkit_policy_decision_download(decision); + else + webkit_policy_decision_use(decision); + break; + default: + /* Use whatever default there is. */ + return FALSE; + } + + return TRUE; +} + +static void +WebViewCb_load_changed(WebKitWebView *webView, WebKitLoadEvent load_event, gpointer user_data) +{ + (void)webView; + (void)load_event; + struct Client *browser = (struct Client *)user_data; + + gtk_widget_set_sensitive(browser->back, webkit_web_view_can_go_back(browser->webView)); + gtk_widget_set_sensitive(browser->forward, webkit_web_view_can_go_forward(browser->webView)); +} + +static char * +detail_tls_certificate_flags(GTlsCertificateFlags tls_errors) +{ + GString *errors = g_string_new(NULL); + + g_string_append_printf(errors, + _("Couldn't verify the TLS certificate to ensure a better security of the " + "connection. You might want to verify your machine and network.\n\n")); + + if(tls_errors & G_TLS_CERTIFICATE_UNKNOWN_CA) + g_string_append_printf(errors, _("Error: The X509 Certificate Authority is unknown.\n")); + + if(tls_errors & G_TLS_CERTIFICATE_BAD_IDENTITY) + g_string_append(errors, _("Error: The given identity doesn't match the expected one.\n")); + + if(tls_errors & G_TLS_CERTIFICATE_NOT_ACTIVATED) + g_string_append(errors, + _("Error: The certificate isn't valid yet. Check your system's clock.\n")); + + if(tls_errors & G_TLS_CERTIFICATE_EXPIRED) + g_string_append(errors, _("Error: The certificate has expired. Check your system's clock.\n")); + + if(tls_errors & G_TLS_CERTIFICATE_REVOKED) + g_string_append(errors, _("Error: The certificate has been revoked.\n")); + + if(tls_errors & G_TLS_CERTIFICATE_INSECURE) + g_string_append(errors, _("Error: The certificate is considered to be insecure.\n")); + + if(tls_errors & G_TLS_CERTIFICATE_GENERIC_ERROR) + g_string_append(errors, _("Error: Some unknown error occurred validating the certificate.\n")); + + return g_string_free(errors, FALSE); +} + +static gboolean +WebViewCb_load_failed_with_tls_errors(WebKitWebView *web_view, + gchar *failing_text, + GTlsCertificate *certificate, + GTlsCertificateFlags errors, + gpointer user_data) +{ + (void)web_view; + (void)certificate; + (void)errors; + struct Client *browser = (struct Client *)user_data; + gchar *error_details = detail_tls_certificate_flags(errors); + gint dialog_response; + +#ifndef USE_LIBSOUP2 + GUri *failing_uri = g_uri_parse(failing_text, G_URI_FLAGS_NONE, NULL); +#else + SoupURI *failing_uri = soup_uri_new(failing_text); +#endif + + GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(browser->window->main_window), + GTK_DIALOG_MODAL & GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_NONE, + _("TLS Error for %s."), + failing_text); + gtk_dialog_add_buttons( + GTK_DIALOG(dialog), _("Temporarily Add Exception"), 1, _("Continue"), 0, NULL); + if(!failing_uri) + { + gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), 1, FALSE); + } + gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s\n", error_details); + + dialog_response = gtk_dialog_run(GTK_DIALOG(dialog)); + + if(dialog_response == 1) + { +#ifndef USE_LIBSOUP2 + webkit_web_context_allow_tls_certificate_for_host( + webkit_web_view_get_context(browser->webView), certificate, g_uri_get_host(failing_uri)); +#else + webkit_web_context_allow_tls_certificate_for_host( + webkit_web_view_get_context(browser->webView), certificate, failing_uri->host); +#endif + webkit_web_view_reload(browser->webView); + } + +#ifndef USE_LIBSOUP2 + /* Calling g_free(failing_uri) ought to be the correct way but this causes a segfault. + * + * - documentation describes it as something which should be free + * - implementation seems to make it a pointer that should be freed + * - epiphany doesn't seems to free/unref it but gnome code seems to frequently have memleaks + * + * Decided to at least continue to try with using g_uri_unref(failing_uri) instead. + * Related fediverse post: + */ + g_uri_unref(failing_uri); +#else + soup_uri_free(failing_uri); +#endif + g_free(error_details); + gtk_widget_destroy(dialog); + + return FALSE; /* propagate the event further */ +} + +static void +web_contextCb_download_started(WebKitWebContext *web_context, + WebKitDownload *webkit_download, + gpointer user_data) +{ + (void)web_context; + struct Client *browser = (struct Client *)user_data; + struct Download *download = malloc(sizeof(struct Download)); + + assert(webkit_download); + + if(download != NULL) + { + download->window = browser->window; + + download_new_entry(webkit_download, download); + + g_signal_connect( + G_OBJECT(webkit_download), "received-data", G_CALLBACK(downloadCb_received_data), download); + g_signal_connect(G_OBJECT(webkit_download), + "created-destination", + G_CALLBACK(downloadCb_created_destination), + download); + g_signal_connect(G_OBJECT(webkit_download), "failed", G_CALLBACK(downloadCb_failed), download); + g_signal_connect( + G_OBJECT(webkit_download), "finished", G_CALLBACK(downloadCb_finished), download); + } + + g_signal_connect(G_OBJECT(webkit_download), + "decide-destination", + G_CALLBACK(downloadCb_decide_destination), + user_data); +} + +static gboolean +locationCb_activate(GtkEntry *location, gpointer user_data) +{ + struct Client *browser = (struct Client *)user_data; + + webkit_web_view_load_uri(browser->webView, + goodwolf_ensure_uri_scheme(gtk_entry_get_text(location), TRUE)); + + return TRUE; +} + +static gboolean +javascriptCb_toggled(GtkButton *javascript, gpointer user_data) +{ + struct Client *browser = (struct Client *)user_data; + + WebKitSettings *settings = webkit_web_view_get_settings(browser->webView); + + webkit_settings_set_enable_javascript_markup( + settings, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(javascript))); + + webkit_web_view_set_settings(browser->webView, settings); + + return TRUE; +} + +static gboolean +auto_load_imagesCb_toggled(GtkButton *auto_load_images, gpointer user_data) +{ + struct Client *browser = (struct Client *)user_data; + + WebKitSettings *settings = webkit_web_view_get_settings(browser->webView); + + webkit_settings_set_auto_load_images( + settings, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(auto_load_images))); + + webkit_web_view_set_settings(browser->webView, settings); + + return TRUE; +} + +static void +backCb_clicked(GtkButton *back, gpointer user_data) +{ + (void)back; + struct Client *browser = (struct Client *)user_data; + + webkit_web_view_go_back(browser->webView); +} + +static void +forwardCb_clicked(GtkButton *forward, gpointer user_data) +{ + (void)forward; + struct Client *browser = (struct Client *)user_data; + + webkit_web_view_go_forward(browser->webView); +} + +static void +printCb_clicked(GtkButton *print, gpointer user_data) +{ + (void)print; + struct Client *browser = (struct Client *)user_data; + + WebKitPrintOperation *print_operation = webkit_print_operation_new(browser->webView); + + webkit_print_operation_run_dialog(print_operation, GTK_WINDOW(browser->window->main_window)); +} + +static gboolean +SearchEntryCb_next__match(GtkSearchEntry *search, gpointer user_data) +{ + (void)search; + struct Client *browser = (struct Client *)user_data; + WebKitFindController *findController = webkit_web_view_get_find_controller(browser->webView); + + webkit_find_controller_search_next(findController); + + return TRUE; +} + +static gboolean +SearchEntryCb_previous__match(GtkSearchEntry *search, gpointer user_data) +{ + (void)search; + struct Client *browser = (struct Client *)user_data; + WebKitFindController *findController = webkit_web_view_get_find_controller(browser->webView); + + webkit_find_controller_search_previous(findController); + + return TRUE; +} + +static gboolean +SearchEntryCb_search__changed(GtkSearchEntry *search, gpointer user_data) +{ + struct Client *browser = (struct Client *)user_data; + WebKitFindController *findController = webkit_web_view_get_find_controller(browser->webView); + const gchar *search_text = gtk_entry_get_text(GTK_ENTRY(search)); + + webkit_find_controller_search(findController, search_text, 0, 0); + + return TRUE; +} + +static gboolean +SearchEntryCb_stop__search(GtkSearchEntry *search, gpointer user_data) +{ + (void)search; + struct Client *browser = (struct Client *)user_data; + WebKitFindController *findController = webkit_web_view_get_find_controller(browser->webView); + + webkit_find_controller_search_finish(findController); + + return TRUE; +} + +static gboolean +widgetCb_drop_button3_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + (void)widget; + (void)user_data; + + // Button3 being right-click on right-handed mode, left-click on left-handed mode + return ((GdkEventButton *)event)->button == 3; +} + +struct Client * +new_browser(struct Window *window, const gchar *target_url, struct Client *old_browser) +{ + struct Client *browser = malloc(sizeof(struct Client)); + target_url = goodwolf_ensure_uri_scheme(target_url, (old_browser == NULL)); + char *goodwolf_l10n = NULL; + + WebKitWebContext *web_context; + + if(browser == NULL) return NULL; + + browser->window = window; + browser->context_id = old_browser == NULL ? context_id_counter++ : old_browser->context_id; + browser->box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(browser->box, "browser__box"); + + browser->toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(browser->toolbar, "browser__toolbar"); + + browser->back = + gtk_button_new_from_icon_name("go-previous-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_widget_set_name(browser->back, "browser__back"); + + browser->forward = gtk_button_new_from_icon_name("go-next-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_widget_set_name(browser->forward, "browser__forward"); + + GtkWidget *toolbar_separator = gtk_separator_new(GTK_ORIENTATION_VERTICAL); + + browser->javascript = gtk_toggle_button_new_with_mnemonic(_("_JS")); + gtk_widget_set_name(browser->javascript, "browser__javascript"); + gtk_widget_set_tooltip_text(browser->javascript, _("Toggle javascript")); + gtk_button_set_relief(GTK_BUTTON(browser->javascript), GTK_RELIEF_NONE); + + browser->auto_load_images = gtk_toggle_button_new_with_mnemonic(_("_IMG")); + gtk_widget_set_name(browser->auto_load_images, "browser__load_images"); + gtk_widget_set_tooltip_text(browser->auto_load_images, _("Toggle loading images automatically")); + gtk_button_set_relief(GTK_BUTTON(browser->auto_load_images), GTK_RELIEF_NONE); + + browser->location = gtk_entry_new(); + gtk_widget_set_name(browser->location, "browser__location"); + + GtkWidget *print = + gtk_button_new_from_icon_name("document-print-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_widget_set_name(browser->back, "browser__print"); + + browser->statusbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(browser->statusbar, "browser__statusbar"); + browser->search = gtk_search_entry_new(); + gtk_widget_set_name(browser->search, "browser__search"); + browser->statuslabel = gtk_label_new(NULL); + gtk_widget_set_name(browser->statuslabel, "browser__statuslabel"); + + if(old_browser == NULL) + { + WebKitWebsiteDataManager *website_data_manager = + (persistent_storage) ? webkit_website_data_manager_new(NULL) + : webkit_website_data_manager_new_ephemeral(); + webkit_website_data_manager_set_itp_enabled(website_data_manager, TRUE); + + web_context = webkit_web_context_new_with_website_data_manager(website_data_manager); + g_object_unref(website_data_manager); + webkit_web_context_set_sandbox_enabled(web_context, TRUE); + webkit_web_context_set_process_model(web_context, + WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES); + webkit_web_context_set_web_extensions_directory(web_context, web_extensions_directory); + webkit_web_context_set_favicon_database_directory(web_context, NULL); + if (persistent_storage) { + char context_id_str[GOODWOLF_CTX_SIZ] = {0, 0, 0, 0, 0, 0, 0}; + if (separated_storage) { + fmt_context_id(browser->context_id, context_id_str, 0); + g_mkdir_with_parents( + g_build_filename(g_get_user_config_dir(), "goodwolf", context_id_str, NULL), + 0755); + } + + webkit_cookie_manager_set_persistent_storage( + webkit_website_data_manager_get_cookie_manager(website_data_manager), + g_build_filename(g_get_user_config_dir(), "goodwolf", context_id_str, "cookies.txt", NULL), + WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT); + webkit_cookie_manager_set_accept_policy( + webkit_website_data_manager_get_cookie_manager(website_data_manager), + WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + } + + g_signal_connect(G_OBJECT(web_context), + "download-started", + G_CALLBACK(web_contextCb_download_started), + browser); + } + else + { + web_context = webkit_web_view_get_context(old_browser->webView); + } + + /* flawfinder: ignore. Consider that g_strsplit is safe enough */ + goodwolf_l10n = getenv("GOODWOLF_L10N"); + + if(goodwolf_l10n != NULL) + { + gchar **languages = g_strsplit(goodwolf_l10n, ":", -1); + webkit_web_context_set_spell_checking_languages(web_context, (const gchar *const *)languages); + g_strfreev(languages); + + webkit_web_context_set_spell_checking_enabled(web_context, TRUE); + } + + WebKitSettings *settings = webkit_settings_new_with_settings(GOODWOLF_WEBKIT_SETTINGS); + if (alt_useragent == TRUE) + webkit_settings_set_user_agent(settings, "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:74.0) Gecko/20100101 Firefox/74.0"); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(browser->javascript), + webkit_settings_get_enable_javascript_markup(settings)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(browser->auto_load_images), + webkit_settings_get_auto_load_images(settings)); + + browser->webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, + "web-context", + web_context, + "related-view", + old_browser == NULL ? NULL : old_browser->webView, + "settings", + settings, + "user-content-manager", + window->content_manager, + NULL)); + gtk_widget_set_name(GTK_WIDGET(browser->webView), "browser__webView"); + if(old_browser == NULL) + { + g_object_unref(web_context); + } + g_object_unref(settings); + + gtk_box_pack_start( + GTK_BOX(browser->toolbar), GTK_WIDGET(browser->back), FALSE, FALSE, GOODWOLF_TOOLBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), + GTK_WIDGET(browser->forward), + FALSE, + FALSE, + GOODWOLF_TOOLBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), + toolbar_separator, + FALSE, + FALSE, + GOODWOLF_TOOLBAR_SEPARATOR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), + GTK_WIDGET(browser->javascript), + FALSE, + FALSE, + GOODWOLF_TOOLBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), + GTK_WIDGET(browser->auto_load_images), + FALSE, + FALSE, + GOODWOLF_TOOLBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), + GTK_WIDGET(browser->location), + TRUE, + TRUE, + GOODWOLF_TOOLBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), print, FALSE, FALSE, GOODWOLF_TOOLBAR_PADDING); + + gtk_container_set_focus_child(GTK_CONTAINER(browser->box), browser->toolbar); + gtk_container_set_focus_child(GTK_CONTAINER(browser->toolbar), browser->location); + + gtk_box_pack_start( + GTK_BOX(browser->box), GTK_WIDGET(browser->toolbar), FALSE, FALSE, GOODWOLF_BOX_PADDING); + gtk_box_pack_start( + GTK_BOX(browser->box), GTK_WIDGET(browser->webView), TRUE, TRUE, GOODWOLF_BOX_PADDING); + + gtk_box_pack_start( + GTK_BOX(browser->box), GTK_WIDGET(browser->statusbar), FALSE, FALSE, GOODWOLF_BOX_PADDING); + + gtk_box_pack_start(GTK_BOX(browser->statusbar), + GTK_WIDGET(browser->search), + FALSE, + FALSE, + GOODWOLF_STATUSBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->statusbar), + GTK_WIDGET(browser->statuslabel), + FALSE, + FALSE, + GOODWOLF_STATUSBAR_PADDING); + + gtk_widget_set_halign(browser->statusbar, GTK_ALIGN_START); + + gtk_label_set_single_line_mode(GTK_LABEL(browser->statuslabel), TRUE); + gtk_label_set_ellipsize(GTK_LABEL(browser->statuslabel), GOODWOLF_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); + + gtk_entry_set_placeholder_text(GTK_ENTRY(browser->search), _("search in current page")); + + /* signals for back/forward buttons */ + g_signal_connect(browser->back, "clicked", G_CALLBACK(backCb_clicked), browser); + g_signal_connect(browser->forward, "clicked", G_CALLBACK(forwardCb_clicked), browser); + /* prevents GtkNotebook from spawning it's context-menu */ + g_signal_connect( + browser->back, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect( + browser->back, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect( + browser->forward, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect( + browser->forward, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + + /* signals for javacript toggle widget */ + g_signal_connect(browser->javascript, "toggled", G_CALLBACK(javascriptCb_toggled), browser); + /* prevents GtkNotebook from spawning it's context-menu */ + g_signal_connect( + browser->javascript, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect( + browser->javascript, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + + /* signals for auto_load_images toggle widget */ + g_signal_connect( + browser->auto_load_images, "toggled", G_CALLBACK(auto_load_imagesCb_toggled), browser); + /* prevents GtkNotebook from spawning it's context-menu */ + g_signal_connect(browser->auto_load_images, + "button-press-event", + G_CALLBACK(widgetCb_drop_button3_event), + NULL); + g_signal_connect(browser->auto_load_images, + "button-release-event", + G_CALLBACK(widgetCb_drop_button3_event), + NULL); + + /* signals for location entry widget */ + g_signal_connect(browser->location, "activate", G_CALLBACK(locationCb_activate), browser); + + /* signals for print button */ + g_signal_connect(print, "clicked", G_CALLBACK(printCb_clicked), browser); + /* prevents GtkNotebook from spawning it's context-menu */ + g_signal_connect(print, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect(print, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + + /* signals for WebView widget */ + g_signal_connect(browser->webView, + "web-process-terminated", + G_CALLBACK(WebViewCb_web_process_terminated), + browser); + g_signal_connect(browser->webView, "notify::uri", G_CALLBACK(WebViewCb_notify__uri), browser); + + g_signal_connect(browser->webView, "notify::title", G_CALLBACK(WebViewCb_notify__title), browser); + g_signal_connect(browser->webView, + "notify::favicon", + G_CALLBACK(WebViewCb_notify__favicon), + browser); + g_signal_connect(browser->webView, + "notify::is-playing-audio", + G_CALLBACK(WebViewCb_notify__is__playing__audio), + browser); + g_signal_connect(browser->webView, + "mouse-target-changed", + G_CALLBACK(WebViewCb_mouse_target_changed), + browser); + g_signal_connect(browser->webView, + "notify::estimated-load-progress", + G_CALLBACK(WebViewCb_notify__estimated_load_progress), + browser); + g_signal_connect(browser->webView, "create", G_CALLBACK(WebViewCb_create), browser); + g_signal_connect(browser->webView, "close", G_CALLBACK(WebViewCb_close), browser); + + g_signal_connect( + browser->webView, "key-press-event", G_CALLBACK(WebViewCb_key_press_event), browser); + g_signal_connect(browser->webView, "scroll-event", G_CALLBACK(WebViewCb_scroll_event), browser); + g_signal_connect( + browser->webView, "permission-request", G_CALLBACK(WebViewCb_permission_request), NULL); + g_signal_connect(browser->webView, "decide-policy", G_CALLBACK(WebViewCb_decide_policy), NULL); + g_signal_connect(browser->webView, + "load-failed-with-tls-errors", + G_CALLBACK(WebViewCb_load_failed_with_tls_errors), + browser); + g_signal_connect(browser->webView, "load-changed", G_CALLBACK(WebViewCb_load_changed), browser); + + /* signals for search widget */ + g_signal_connect(browser->search, "next-match", G_CALLBACK(SearchEntryCb_next__match), browser); + g_signal_connect( + browser->search, "previous-match", G_CALLBACK(SearchEntryCb_previous__match), browser); + g_signal_connect( + browser->search, "search-changed", G_CALLBACK(SearchEntryCb_search__changed), browser); + g_signal_connect(browser->search, "stop-search", G_CALLBACK(SearchEntryCb_stop__search), browser); + + /* signals for box container */ + g_signal_connect(browser->box, "key-press-event", G_CALLBACK(boxCb_key_press_event), browser); + + if(old_browser == NULL) webkit_web_view_load_uri(browser->webView, target_url); + + return browser; +} + +/* goodwolf_new_tab: Inserts struct Client *browser in GtkNotebook *notebook + * and optionally switches selected tab to it. + * + * returns: + * 0 : Ran successfully + * -1 : Failed to insert a page for browser->box + * -2 : browser is NULL + */ +int +goodwolf_new_tab(GtkNotebook *notebook, struct Client *browser, bool auto_switch) +{ + gint current_page = gtk_notebook_get_current_page(notebook); + gchar *title = _("New tab"); + + if(browser == NULL) return -2; + + gtk_widget_show_all(browser->box); + + if(gtk_notebook_insert_page(notebook, browser->box, NULL, (current_page + 1)) == -1) return -1; + + gtk_notebook_set_tab_reorderable(notebook, browser->box, TRUE); + gtk_notebook_set_tab_label(notebook, browser->box, goodwolf_new_tab_box(title, browser)); + gtk_notebook_set_menu_label_text(GTK_NOTEBOOK(notebook), browser->box, title); + + gtk_widget_queue_draw(GTK_WIDGET(notebook)); + + if(auto_switch) + { + gtk_notebook_set_current_page(notebook, gtk_notebook_page_num(notebook, browser->box)); + } + + return 0; +} + +static void +new_tabCb_clicked(GtkButton *new_tab, gpointer user_data) +{ + (void)new_tab; + struct Window *window = (struct Window *)user_data; + struct Client *browser = new_browser(window, NULL, NULL); + + goodwolf_new_tab(GTK_NOTEBOOK(window->notebook), browser, TRUE); +} + +static void +closeCb_clicked(GtkButton *close, gpointer user_data) +{ + (void)close; + struct Client *browser = (struct Client *)user_data; + + webkit_web_view_try_close(browser->webView); +} + +static void +notebookCb_switch__page(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data) +{ + (void)page_num; + struct Window *window = (struct Window *)user_data; + GtkWidget *label = gtk_notebook_get_tab_label(notebook, page); + + // TODO: Maybe find a better way to store the title + gtk_window_set_title(GTK_WINDOW(window->main_window), gtk_widget_get_tooltip_text(label)); +} + +void +content_managerCb_ready(GObject *store, GAsyncResult *result, gpointer user_data) +{ + (void)store; + struct Window *window = (struct Window *)user_data; + GError *err = NULL; + + WebKitUserContentFilter *filter = + webkit_user_content_filter_store_load_finish(window->content_store, result, &err); + + if(filter == NULL) + { + if(err == NULL) + { + fprintf(stderr, _("goodwolf: failed to load content-filter, err: [%d] %s\n"), -1, "unknown"); + } + else + { + fprintf(stderr, + _("goodwolf: failed to load content-filter, err: [%d] %s\n"), + err->code, + err->message); + } + } + else + { + fprintf(stderr, _("goodwolf: content-filter loaded, adding to content-manager…\n")); + webkit_user_content_manager_add_filter(window->content_manager, filter); + } +} + +static void +storeCb_finish(WebKitUserContentFilterStore *store, GAsyncResult *result, gpointer user_data) +{ + (void)store; + struct Window *window = (struct Window *)user_data; + GError *err = NULL; + + WebKitUserContentFilter *filter = + webkit_user_content_filter_store_save_finish(window->content_store, result, &err); + + if(filter == NULL) + { + if(err == NULL) + { + fprintf(stderr, + _("goodwolf: failed to compile content-filters.json, err: [%d] %s\n"), + -1, + "unknown"); + } + else + { + fprintf(stderr, + _("goodwolf: failed to compile content-filters.json, err: [%d] %s\n"), + err->code, + err->message); + } + } + else + { + webkit_user_content_filter_store_load( + window->content_store, "a", NULL, content_managerCb_ready, window); + } +} + +void +tray_icon_on_click(GtkStatusIcon *status_icon, gpointer main_window_ptr) +{ + GtkWidget *main_window = GTK_WIDGET(main_window_ptr); + if (gtk_widget_is_visible(main_window)) + gtk_widget_hide(main_window); + else + gtk_widget_show(main_window); +} + +static GtkStatusIcon *create_tray_icon(const struct Window *window) { + GtkStatusIcon *tray_icon; + + tray_icon = gtk_status_icon_new(); + g_signal_connect(G_OBJECT(tray_icon), "activate", G_CALLBACK(tray_icon_on_click), window->main_window); + gtk_status_icon_set_from_icon_name(tray_icon, "goodwolf"); + gtk_status_icon_set_tooltip_text(tray_icon, "Badwolf"); + gtk_status_icon_set_visible(tray_icon, TRUE); + + return tray_icon; +} + +int +main(int argc, char *argv[]) +{ + if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'h') { + printf("\ +goodwolf [OPTIONS] [URLs]\n\n\ +Options:\n\ +-s DD Specifies a custom favicon size, where DD is a two digit number\n\ +-nl Tabs won't have a label (page title)\n\ +-cl Tabs will have a context label (text that identifies every tab)\n\ +-c You won't be able to add or remove any tabs, other than those specified\n\ + as parameters\n\ +-t Adds a tray icon. Clicking it toggles visibility of the browser window.\n\ +-u All tabs will use an alternative UserAgent\n\ +-p Persistent storage, meaning non-session cookies will be stored on drive\n\ +-g Separated storage, meaning persistent storage will be done separately for\n\ + each tab context. Doesn't do anything if the -p option isn't selected.\n" + ); + return 0; + } + + struct Window *window = &(struct Window){NULL, NULL, NULL, NULL, NULL, NULL}; + GApplication *application; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, DATADIR "/locale"); + bind_textdomain_codeset(PACKAGE, "UTF-8"); + textdomain(PACKAGE); + + application = g_application_new("me.hacktivis.goodwolf", + G_APPLICATION_HANDLES_COMMAND_LINE | + G_APPLICATION_SEND_ENVIRONMENT | G_APPLICATION_NON_UNIQUE); + g_application_register(application, NULL, NULL); + //g_application_activate(application); + + gtk_init(&argc, &argv); + + fprintf(stderr, _("Running Badwolf version: %s\n"), version); + fprintf(stderr, + _("Buildtime WebKit version: %d.%d.%d\n"), + WEBKIT_MAJOR_VERSION, + WEBKIT_MINOR_VERSION, + WEBKIT_MICRO_VERSION); + fprintf(stderr, + _("Runtime WebKit version: %d.%d.%d\n"), + webkit_get_major_version(), + webkit_get_minor_version(), + webkit_get_micro_version()); + + web_extensions_directory = + g_build_filename(g_get_user_data_dir(), "goodwolf", "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); + window->downloads_tab = goodwolf_downloads_tab_new(); + window->content_manager = webkit_user_content_manager_new(); + + gchar *contentFilterPath = + g_build_filename(g_get_user_config_dir(), g_get_prgname(), "content-filters.json", NULL); + GFile *contentFilterFile = g_file_new_for_path(contentFilterPath); + fprintf(stderr, _("content-filters file set to: %s\n"), contentFilterPath); + + gchar *filtersPath = g_build_filename(g_get_user_cache_dir(), g_get_prgname(), "filters", NULL); + window->content_store = webkit_user_content_filter_store_new(filtersPath); + + webkit_user_content_filter_store_save_from_file(window->content_store, + "a", + contentFilterFile, + NULL, + (GAsyncReadyCallback)storeCb_finish, + window); + + gtk_window_set_default_size( + GTK_WINDOW(window->main_window), GOODWOLF_DEFAULT_WIDTH, GOODWOLF_DEFAULT_HEIGHT); + gtk_window_set_role(GTK_WINDOW(window->main_window), "browser"); + gtk_window_set_icon_name(GTK_WINDOW(window->main_window), "goodwolf"); + + gchar *provider_path_app = g_build_filename(DATADIR, "interface.css", NULL); + /* flawfinder: ignore, just a presence check */ + if(access(provider_path_app, R_OK) == 0) + { + GtkCssProvider *css_provider_app = gtk_css_provider_new(); + gtk_css_provider_load_from_path(css_provider_app, provider_path_app, NULL); + gtk_style_context_add_provider_for_screen( + gtk_widget_get_screen(GTK_WIDGET(window->main_window)), + GTK_STYLE_PROVIDER(css_provider_app), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + g_free(provider_path_app); + + gchar *provider_path_user = + g_build_filename(g_get_user_data_dir(), "goodwolf", "interface.css", NULL); + /* flawfinder: ignore, just a presence check */ + if(access(provider_path_user, R_OK) == 0) + { + GtkCssProvider *css_provider_user = gtk_css_provider_new(); + gtk_css_provider_load_from_path(css_provider_user, provider_path_user, NULL); + gtk_style_context_add_provider_for_screen( + gtk_widget_get_screen(GTK_WIDGET(window->main_window)), + GTK_STYLE_PROVIDER(css_provider_user), + GTK_STYLE_PROVIDER_PRIORITY_USER); + } + g_free(provider_path_user); + + gtk_widget_set_tooltip_text(window->new_tab, _("Open new tab")); + + gtk_notebook_set_action_widget(GTK_NOTEBOOK(window->notebook), window->new_tab, GTK_PACK_END); + gtk_notebook_set_scrollable(GTK_NOTEBOOK(window->notebook), TRUE); + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(window->notebook), GOODWOLF_TAB_POSITION); + gtk_notebook_popup_enable(GTK_NOTEBOOK(window->notebook)); + + gtk_container_add(GTK_CONTAINER(window->main_window), window->notebook); + gtk_widget_queue_draw(window->notebook); + + goodwolf_downloads_tab_attach(window); + + g_signal_connect( + window->main_window, "key-press-event", G_CALLBACK(main_windowCb_key_press_event), window); + + g_signal_connect(window->main_window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + g_signal_connect(window->new_tab, "clicked", G_CALLBACK(new_tabCb_clicked), window); + g_signal_connect(window->notebook, "switch-page", G_CALLBACK(notebookCb_switch__page), window); + + while (argc > 1 && argv[1][0] == '-') { + if (argv[1][1] == 'n' && argv[1][2] == 'l') + tabs_no_label = TRUE; + else if (argv[1][1] == 'c' && argv[1][2] == 'l') + tabs_context_label = TRUE; + else if (argv[1][1] == 'c') + tabs_constant = TRUE; + else if (argv[1][1] == 't') + tray_enabled = TRUE; + else if (argv[1][1] == 'u') + alt_useragent = TRUE; + else if (argv[1][1] == 'p') + persistent_storage = TRUE; + else if (argv[1][1] == 'g') + separated_storage = TRUE; + else if (argv[1][1] == 's') { + argv++; + argc--; + custom_favicon_size = (argv[1][0] - '0') * 10 + argv[1][1] - '0'; + } + + argv++; + argc--; + } + + if (!tabs_constant) + gtk_widget_show(window->new_tab); + gtk_widget_show_all(window->main_window); + + if(argc == 1) + goodwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, NULL, NULL), FALSE); + else + for(int i = 1; i < argc; ++i) + goodwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, argv[i], NULL), TRUE); + + gtk_notebook_set_current_page(GTK_NOTEBOOK(window->notebook), 1); + + if (tray_enabled) + create_tray_icon(window); + + gtk_main(); + + g_object_unref(bookmarks_completion_model); + +#if 0 + /* TRANSLATOR Ignore this entry. Done for forcing Unicode in xgettext. */ + _("ø"); +#endif + + return 0; +} diff --git a/goodwolf.desktop b/goodwolf.desktop new file mode 100644 index 0000000..c597ece --- /dev/null +++ b/goodwolf.desktop @@ -0,0 +1,15 @@ +# https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/ +[Desktop Entry] +Version=1.1 +Type=Application +Categories=Network;WebBrowser +Comment=A minimalist and privacy-oriented web browser +Comment[fr]=Un navigateur web minimaliste et orienté vers le respect de la vie privée +Exec=goodwolf %U +GenericName=Web Browser +GenericName[fr]=Navigateur Web +Icon=goodwolf +Keywords=Internet;WWW;Browser;Web;WebKit;WebKitGTK +Keywords[fr]=Internet;WWW;Browser;Web;Surfer;Navigateur;WebKit;WebKitGTK +MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https +Name=Badwolf diff --git a/goodwolf.fr.1 b/goodwolf.fr.1 new file mode 100644 index 0000000..8252127 --- /dev/null +++ b/goodwolf.fr.1 @@ -0,0 +1,164 @@ +.\" BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser +.\" Copyright © 2019-2022 Badwolf Authors +.\" SPDX-License-Identifier: BSD-3-Clause +.\"******************************************************************* +.\" +.\" This file was generated with po4a. Translate the source file. +.\" +.\"******************************************************************* +.Dd 2022-04-06 +.Dt GOODWOLF 1 +.Os +.Sh NAME +.Nm goodwolf +.Nd navigateur minimaliste et orienté vie-privée basé sur WebKitGTK +.Sh SYNOPSIS +.Nm +.Op Ar options webkit/gtk +.Op Ar URLs or chemins +.Sh DESCRIPTION +.Nm +est un navigateur minimaliste qui prend soin de la vie privée, c'est +basé WebKitGTK et accept donc les options et variables d'environements de +WebKitGTK et ses dépendances, malheuresement il ne semble pas avoir de pages +de man pour celles-ci. +.Pp +Une configuration dynamique spécifique à +.Nm +sera sans doute rajoutée +dans une version suivante. +.Sh RACCOURCIS +Cette section liste les raccourcis et leurs actions, chaque point est décris +avec le widget actif ou avec +.Aq tout +quand il fonctionne sur la fenêtre +entière, suivit par le raccourcis. +.Bl -tag -width Ds +.It vueweb Ctrl-Défilement +(Dé)-Grossir le zoom de la page. +.It vueweb Ctrl-0 +Remettre le zoom de la page à 100%. +.It tout Ctrl-t +Créer un nouvel onglet (dans une nouvelle session, comme un apuis sur le +bouton dédié) +.It navigateur Ctrl-F4, navigateur Alt-d +Fermer l'onglet courant. +.It navigateur Ctrl-f +Aller dans le champ de recherche. +.It navigateur Ctrl-l +Aller dans la barre d'URL. +.It navigateur Ctrl-Maj-r / Ctrl-r, navigateur F5 +Recharger le contenu dans l'onglet courant (avec/sans nettoyer le cache). +.It navigateur Échap +Arrêter le chargement dans l'onglet courant. +.It navigateur F7 +(Dé)-Activer la navigation par curseur. +.It navigateur F12 +Ouvrir les outils de dévelopement. +.It navigateur Ctrl-[ / Ctrl-] +Naviguer dans l'historique courrant précédent/suivant. +.It navigateur Ctrl-p +Imprimer la page courante. (ouvre une nouvelle fenêtre) +.It tout Alt-Gauche / Alt-Droite +Aller à l'onglet précédent/suivant. +.It tout F1 +Montrer la fenêtre d'À Propos. +.It tout Alt-n +Où n est n'importe quelle touche de la barre numérique. +Aller à l'onglet n, 0 va au dernier. +.El +.Ss PAR DÉFAULTS +Ceci est une liste incomplète des raccourcis par défaults dans WebKit/GTK: +.Bl -tag -width Ds +.It tout Ctrl-PageUp / Ctrl-PageDown +Aller à l'onglet précédent/suivant. +.It recherche Ctrl-g / Ctrl-Maj-g +Quand le champ de recherche est actif, aller au résultat précédent/suivant. +.It recherche Échap +Annule la recherche actuelle. +.El +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev GOODWOLF_L10N +A colon-separated list in the form lang_COUNTRY where lang is in ISO-639 and +COUNTRY in ISO-3166. For example +.Ic GOODWOLF_L10N="en_GB:fr_FR:de_DE" . +When this variable isn't set, spelling isn't activated. A more generic +variable name is also intended to be used in the future. +.Pp +Pour avoir la liste des dictionaires installés, executez: +.Ic enchant-lsmod-2 -list-dicts +ou avant enchant 2.0: +.Ic enchant-lsmod -list-dicts +.El +.Sh FICHIERS +Les chemins suivants utilisent la syntaxe de +.Xr sh 1 +pour correctement +supporter la XDG Base Directory Specification, vous pouver utiliser la +commande +.Xr echo 1 +pour vérifier où cela se trouve sur votre système. +.Pp +.Bl -tag -width Ds -compact +.It Pa ${XDG_CONFIG_HOME:-$HOME/.config}/goodwolf/content-filters.json +Fichier content-filter spécifique à WebKit, cela permet de blocker le +contenu indésirable (pubs, nagware, …). +Pour une introduction au format, voir (en anglais): +.Lk https://webkit.org/blog/3476/content-blockers-first-look/ +.Lk https://webkit.org/blog/4062/targeting-domains-with-content-blockers/ +.Lk https://developer.apple.com/documentation/safariservices/creating_a_content_blocker +.Pp +Pour un convertiseur de filtres compatibles AdBlockPlus, essayez: +.Lk https://gitlab.com/eyeo/adblockplus/abp2blocklist +.Pp +Pour un fichier prêt à l'usage (que vous devrez mettre à jour +périodiquement), essayez: +.Lk https://easylist-downloads.adblockplus.org/easylist_min_content_blocker.json +.It Pa ${XDG_CACHE_HOME:-$HOME/.cache}/goodwolf/filters +Stockage des filtres compilés, les fichiers présents sont automatiquement +générés et ne doivent pas être édité. +Documenté ici seulement pour les isolations ou la gestion des contrôle +d'accès. +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/goodwolf/bookmarks.xbel +Fichier XBEL (XML Bookmark Exchange Language; Language XML d'Échange de +Marques-Pages), connu pour être supporté par: +.Xr elinks 1 , +.Xr konqueror 1 , +.Xr kbookmarkeditor 1 . Faire un lien symbolique depuisleurs chemins fonctionne mais vous pouvez aussi utiliser des XInclude pour fusionner plusieurs fichiers XBEL. +.Pp +Pour plus d'information à propos du format, voir (en anglais): +.Lk http://pyxml.sourceforge.net/topics/xbel/ +.Pp +Pour un example de fichier XBEL voir: +.Lk https://hacktivis.me/bookmarks.xbel +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/goodwolf/webkit-web-extension/ +Répertoire contenant les +.Lk https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebExtension.html WebKitWebExtensions +pour être chargés dans +.Nm . Note\ : Ce ne sont pas les Web-Extensions basé sur JavaScript et supporté par Firefox ou Chrome, mais du code natif dans des shared objects qui utilisent l'API WebKitGTK. +.Pp +Des examples de quelques extensions utiles peuvent être trouvés sur: +.Lk https://hacktivis.me/git/goodwolf-extensions +.It Pa ${DATADIR:-/usr/local/share}/goodwolf/interface.css +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/goodwolf/interface.css +.\" GNOME can't even into doing any redirections of the few docs available +Fichiers CSS (respectivement système et utilisateur) pour changer le style +de l'interface de +.Nm . +Voir +.Lk http://web.archive.org/web/20210420214617/https://developer.gnome.org/gtk3/stable/chap-css-properties.html +pour la liste des propriétés disponibles. +.Pp +Pour tester les styles je recommende d'utiliser la variable d'environemnt +.Ev GTK_DEBUG=interactive +et d'aller à l'onglet CSS. +.El +.Sh AUTHORS +.An Haelwenn (lanodan) Monnier Aq Mt contact+goodwolf@hacktivis.me +.Sh BUGS +Vous pouvez soumettre des contributions ou des tickets à +.Lk https://sr.ht/~lanodan/goodwolf/ +avec +.Xr git-send-email 1 +pour les modifications. diff --git a/goodwolf.h b/goodwolf.h new file mode 100644 index 0000000..df72f00 --- /dev/null +++ b/goodwolf.h @@ -0,0 +1,51 @@ +#ifndef GOODWOLF_H_INCLUDED +#define GOODWOLF_H_INCLUDED + +#include +#include /* uint64_t */ +#include + +#if !WEBKIT_CHECK_VERSION(2, 32, 0) +#error WebkitGTK 2.32.0 is the latest supported version for goodwolf. +#endif + +extern const gchar *homepage; +extern const gchar *version; + +struct Window +{ + GtkWidget *main_window; + GtkWidget *notebook; + GtkWidget *new_tab; + GtkWidget *downloads_tab; + WebKitUserContentManager *content_manager; + WebKitUserContentFilterStore *content_store; +}; + +struct Client +{ + GtkWidget *box; + + GtkWidget *toolbar; + GtkWidget *back; + GtkWidget *forward; + GtkWidget *javascript; + GtkWidget *auto_load_images; + GtkWidget *location; + + uint64_t context_id; + WebKitWebView *webView; + struct Window *window; + + GtkWidget *statusbar; + GtkWidget *statuslabel; + GtkWidget *search; +}; + +GtkWidget *goodwolf_new_tab_box(const gchar *title, struct Client *browser); +void webView_tab_label_change(struct Client *browser, const gchar *title); +struct Client * +new_browser(struct Window *window, const gchar *target_url, struct Client *old_browser); +int goodwolf_new_tab(GtkNotebook *notebook, struct Client *browser, bool auto_switch); +gint goodwolf_get_tab_position(GtkContainer *notebook, GtkWidget *child); +#endif /* GOODWOLF_H_INCLUDED */ diff --git a/goodwolf.inkscape.svg b/goodwolf.inkscape.svg new file mode 100644 index 0000000..973f85b --- /dev/null +++ b/goodwolf.inkscape.svg @@ -0,0 +1,161 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/goodwolf.svg b/goodwolf.svg new file mode 100644 index 0000000..bbf3777 --- /dev/null +++ b/goodwolf.svg @@ -0,0 +1,129 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/hicolor/128x128/apps/badwolf.png b/icons/hicolor/128x128/apps/badwolf.png deleted file mode 100644 index 922295a..0000000 Binary files a/icons/hicolor/128x128/apps/badwolf.png and /dev/null differ diff --git a/icons/hicolor/128x128/apps/goodwolf.png b/icons/hicolor/128x128/apps/goodwolf.png new file mode 100644 index 0000000..922295a Binary files /dev/null and b/icons/hicolor/128x128/apps/goodwolf.png differ diff --git a/icons/hicolor/24x24/apps/badwolf.png b/icons/hicolor/24x24/apps/badwolf.png deleted file mode 100644 index 1e5bb8c..0000000 Binary files a/icons/hicolor/24x24/apps/badwolf.png and /dev/null differ diff --git a/icons/hicolor/24x24/apps/goodwolf.png b/icons/hicolor/24x24/apps/goodwolf.png new file mode 100644 index 0000000..1e5bb8c Binary files /dev/null and b/icons/hicolor/24x24/apps/goodwolf.png differ diff --git a/icons/hicolor/256x256/apps/badwolf.png b/icons/hicolor/256x256/apps/badwolf.png deleted file mode 100644 index c2d2519..0000000 Binary files a/icons/hicolor/256x256/apps/badwolf.png and /dev/null differ diff --git a/icons/hicolor/256x256/apps/goodwolf.png b/icons/hicolor/256x256/apps/goodwolf.png new file mode 100644 index 0000000..c2d2519 Binary files /dev/null and b/icons/hicolor/256x256/apps/goodwolf.png differ diff --git a/icons/hicolor/32x32/apps/badwolf.png b/icons/hicolor/32x32/apps/badwolf.png deleted file mode 100644 index 8dc45c8..0000000 Binary files a/icons/hicolor/32x32/apps/badwolf.png and /dev/null differ diff --git a/icons/hicolor/32x32/apps/goodwolf.png b/icons/hicolor/32x32/apps/goodwolf.png new file mode 100644 index 0000000..8dc45c8 Binary files /dev/null and b/icons/hicolor/32x32/apps/goodwolf.png differ diff --git a/icons/hicolor/48x48/apps/badwolf.png b/icons/hicolor/48x48/apps/badwolf.png deleted file mode 100644 index 09c7d59..0000000 Binary files a/icons/hicolor/48x48/apps/badwolf.png and /dev/null differ diff --git a/icons/hicolor/48x48/apps/goodwolf.png b/icons/hicolor/48x48/apps/goodwolf.png new file mode 100644 index 0000000..09c7d59 Binary files /dev/null and b/icons/hicolor/48x48/apps/goodwolf.png differ diff --git a/icons/hicolor/64x64/apps/badwolf.png b/icons/hicolor/64x64/apps/badwolf.png deleted file mode 100644 index fdbcb59..0000000 Binary files a/icons/hicolor/64x64/apps/badwolf.png and /dev/null differ diff --git a/icons/hicolor/64x64/apps/goodwolf.png b/icons/hicolor/64x64/apps/goodwolf.png new file mode 100644 index 0000000..fdbcb59 Binary files /dev/null and b/icons/hicolor/64x64/apps/goodwolf.png differ diff --git a/icons/hicolor/scalable/apps/badwolf.svg b/icons/hicolor/scalable/apps/badwolf.svg deleted file mode 100644 index fccd2ea..0000000 --- a/icons/hicolor/scalable/apps/badwolf.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/icons/hicolor/scalable/apps/goodwolf.svg b/icons/hicolor/scalable/apps/goodwolf.svg new file mode 100644 index 0000000..fccd2ea --- /dev/null +++ b/icons/hicolor/scalable/apps/goodwolf.svg @@ -0,0 +1,2 @@ + + diff --git a/keybindings.c b/keybindings.c index 7108acd..e7e0846 100644 --- a/keybindings.c +++ b/keybindings.c @@ -4,7 +4,7 @@ #include "keybindings.h" -#include "badwolf.h" +#include "goodwolf.h" #include /* _() */ @@ -14,7 +14,7 @@ about_dialogCb_activate_link(GtkAboutDialog *about_dialog, gchar *uri, gpointer (void)about_dialog; struct Window *window = (struct Window *)user_data; - badwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, uri, NULL), TRUE); + goodwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, uri, NULL), TRUE); gtk_window_close(GTK_WINDOW(about_dialog)); @@ -22,7 +22,7 @@ about_dialogCb_activate_link(GtkAboutDialog *about_dialog, gchar *uri, gpointer } static void -badwolf_about_dialog(GtkWindow *main_window, gpointer user_data) +goodwolf_about_dialog(GtkWindow *main_window, gpointer user_data) { struct Window *window = (struct Window *)user_data; GtkWidget *about_dialog = gtk_about_dialog_new(); @@ -42,11 +42,11 @@ badwolf_about_dialog(GtkWindow *main_window, gpointer user_data) "SPDX-License-Identifier: BSD-3-Clause"); gtk_about_dialog_set_copyright( GTK_ABOUT_DIALOG(about_dialog), - "2019-2021 Badwolf Authors "); + "2019-2021 Badwolf Authors "); gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about_dialog), homepage); gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about_dialog), comments); gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about_dialog), version); - gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(about_dialog), "badwolf"); + gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(about_dialog), "goodwolf"); g_signal_connect(about_dialog, "activate-link", G_CALLBACK(about_dialogCb_activate_link), window); @@ -112,7 +112,7 @@ commonCb_key_press_event(struct Window *window, GdkEvent *event, struct Client * { case GDK_KEY_Page_Down: gtk_notebook_next_page(notebook); return TRUE; case GDK_KEY_Page_Up: gtk_notebook_prev_page(notebook); return TRUE; - case GDK_KEY_t: badwolf_new_tab(notebook, new_browser(window, NULL, NULL), TRUE); return TRUE; + case GDK_KEY_t: goodwolf_new_tab(notebook, new_browser(window, NULL, NULL), TRUE); return TRUE; } } } @@ -151,7 +151,7 @@ commonCb_key_press_event(struct Window *window, GdkEvent *event, struct Client * { switch(((GdkEventKey *)event)->keyval) { - case GDK_KEY_F1: badwolf_about_dialog(GTK_WINDOW(window->main_window), window); return TRUE; + case GDK_KEY_F1: goodwolf_about_dialog(GTK_WINDOW(window->main_window), window); return TRUE; } } diff --git a/keybindings.h b/keybindings.h index bec9189..a690ee0 100644 --- a/keybindings.h +++ b/keybindings.h @@ -1,6 +1,6 @@ #ifndef KEYBINDINGS_H_INCLUDED #define KEYBINDINGS_H_INCLUDED -#include "badwolf.h" +#include "goodwolf.h" #include #include diff --git a/po/manpage.pot b/po/manpage.pot index c41e121..dce2850 100644 --- a/po/manpage.pot +++ b/po/manpage.pot @@ -18,53 +18,53 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" #. type: Dd -#: badwolf.1:4 +#: goodwolf.1:4 #, no-wrap msgid "2022-04-06" msgstr "" #. type: Dt -#: badwolf.1:5 +#: goodwolf.1:5 #, no-wrap -msgid "BADWOLF 1" +msgid "GOODWOLF 1" msgstr "" #. type: Sh -#: badwolf.1:7 +#: goodwolf.1:7 #, no-wrap msgid "NAME" msgstr "" #. type: Plain text -#: badwolf.1:9 -msgid "E<.Nm badwolf>" +#: goodwolf.1:9 +msgid "E<.Nm goodwolf>" msgstr "" #. type: Nd -#: badwolf.1:9 +#: goodwolf.1:9 #, no-wrap msgid "minimalist and privacy-oriented web browser based on WebKitGTK" msgstr "" #. type: Sh -#: badwolf.1:10 +#: goodwolf.1:10 #, no-wrap msgid "SYNOPSIS" msgstr "" #. type: Plain text -#: badwolf.1:14 +#: goodwolf.1:14 msgid "E<.Nm> E<.Op Ar webkit/gtk options> E<.Op Ar URLs or paths>" msgstr "" #. type: Sh -#: badwolf.1:14 +#: goodwolf.1:14 #, no-wrap msgid "DESCRIPTION" msgstr "" #. type: Plain text -#: badwolf.1:17 +#: goodwolf.1:17 msgid "" "E<.Nm> is a minimalist browser that cares about privacy, it is based on " "WebKitGTK and thus also accepts WebKitGTK (and dependencies) flags and " @@ -73,20 +73,20 @@ msgid "" msgstr "" #. type: Plain text -#: badwolf.1:21 +#: goodwolf.1:21 msgid "" "Runtime configuration specific to E<.Nm> will probably get added at a later " "release." msgstr "" #. type: Sh -#: badwolf.1:21 +#: goodwolf.1:21 #, no-wrap msgid "KEYBINDINGS" msgstr "" #. type: Plain text -#: badwolf.1:25 +#: goodwolf.1:25 msgid "" "The following section lists the keybinding by their action, each item is " "described by the widget the focus is on or E<.Aq any> if it works for the " @@ -94,246 +94,246 @@ msgid "" msgstr "" #. type: It -#: badwolf.1:26 +#: goodwolf.1:26 #, no-wrap msgid "webview Ctrl-Scroll" msgstr "" #. type: Plain text -#: badwolf.1:28 +#: goodwolf.1:28 msgid "Zooms the webpage in/out." msgstr "" #. type: It -#: badwolf.1:28 +#: goodwolf.1:28 #, no-wrap msgid "webview Ctrl-0" msgstr "" #. type: Plain text -#: badwolf.1:30 +#: goodwolf.1:30 msgid "Resets webpage zoom to 100%." msgstr "" #. type: It -#: badwolf.1:30 +#: goodwolf.1:30 #, no-wrap msgid "any Ctrl-t" msgstr "" #. type: Plain text -#: badwolf.1:32 +#: goodwolf.1:32 msgid "Creates a new tab (in a new session, similar as pressing the button)" msgstr "" #. type: It -#: badwolf.1:32 +#: goodwolf.1:32 #, no-wrap msgid "browser Ctrl-F4, browser Alt-d" msgstr "" #. type: Plain text -#: badwolf.1:34 +#: goodwolf.1:34 msgid "Closes the current tab" msgstr "" #. type: It -#: badwolf.1:34 +#: goodwolf.1:34 #, no-wrap msgid "browser Ctrl-f" msgstr "" #. type: Plain text -#: badwolf.1:36 +#: goodwolf.1:36 msgid "Focuses on the search entry" msgstr "" #. type: It -#: badwolf.1:36 +#: goodwolf.1:36 #, no-wrap msgid "browser Ctrl-l" msgstr "" #. type: Plain text -#: badwolf.1:38 +#: goodwolf.1:38 msgid "Focuses on the location(URL) entry" msgstr "" #. type: It -#: badwolf.1:38 +#: goodwolf.1:38 #, no-wrap msgid "browser Ctrl-Shift-r / Ctrl-r, browser F5" msgstr "" #. type: Plain text -#: badwolf.1:40 +#: goodwolf.1:40 msgid "Reloads the content in the current tab (with/without clearing cache)" msgstr "" #. type: It -#: badwolf.1:40 +#: goodwolf.1:40 #, no-wrap msgid "browser Escape" msgstr "" #. type: Plain text -#: badwolf.1:42 +#: goodwolf.1:42 msgid "Stops loading the content in the current tab" msgstr "" #. type: It -#: badwolf.1:42 +#: goodwolf.1:42 #, no-wrap msgid "browser F7" msgstr "" #. type: Plain text -#: badwolf.1:44 +#: goodwolf.1:44 msgid "Toggles caret browsing." msgstr "" #. type: It -#: badwolf.1:44 +#: goodwolf.1:44 #, no-wrap msgid "browser F12" msgstr "" #. type: Plain text -#: badwolf.1:46 +#: goodwolf.1:46 msgid "Opens the web inspector." msgstr "" #. type: It -#: badwolf.1:46 +#: goodwolf.1:46 #, no-wrap msgid "browser Ctrl-[ / Ctrl-]" msgstr "" #. type: Plain text -#: badwolf.1:48 +#: goodwolf.1:48 msgid "Go back/forward in current tab's history" msgstr "" #. type: It -#: badwolf.1:48 +#: goodwolf.1:48 #, no-wrap msgid "browser Ctrl-p" msgstr "" #. type: Plain text -#: badwolf.1:50 +#: goodwolf.1:50 msgid "Print the current page. (spawns a dialog)" msgstr "" #. type: It -#: badwolf.1:50 +#: goodwolf.1:50 #, no-wrap msgid "any Alt-Left / Alt-Right" msgstr "" #. type: Plain text -#: badwolf.1:52 badwolf.1:63 +#: goodwolf.1:52 goodwolf.1:63 msgid "Go to the previous/next tab" msgstr "" #. type: It -#: badwolf.1:52 +#: goodwolf.1:52 #, no-wrap msgid "any F1" msgstr "" #. type: Plain text -#: badwolf.1:54 +#: goodwolf.1:54 msgid "Shows the about dialog" msgstr "" #. type: It -#: badwolf.1:54 +#: goodwolf.1:54 #, no-wrap msgid "any Alt-n" msgstr "" #. type: Plain text -#: badwolf.1:57 +#: goodwolf.1:57 msgid "Where n is any numeric-row key. Go to the n-th tab, 0 goes to the last one." msgstr "" #. type: Ss -#: badwolf.1:58 +#: goodwolf.1:58 #, no-wrap msgid "DEFAULT ONES" msgstr "" #. type: Plain text -#: badwolf.1:60 +#: goodwolf.1:60 msgid "Here is a incomplete list of the default Webkit/GTK keybindings:" msgstr "" #. type: It -#: badwolf.1:61 +#: goodwolf.1:61 #, no-wrap msgid "any Ctrl-PageUp / Ctrl-PageDown" msgstr "" #. type: It -#: badwolf.1:63 +#: goodwolf.1:63 #, no-wrap msgid "search Ctrl-g / Ctrl-Shift-g" msgstr "" #. type: Plain text -#: badwolf.1:65 +#: goodwolf.1:65 msgid "When the search box is focused it goes to the Next/Previous search term." msgstr "" #. type: It -#: badwolf.1:65 +#: goodwolf.1:65 #, no-wrap msgid "search Escape" msgstr "" #. type: Plain text -#: badwolf.1:67 +#: goodwolf.1:67 msgid "Cancels current search" msgstr "" #. type: Sh -#: badwolf.1:68 +#: goodwolf.1:68 #, no-wrap msgid "ENVIRONMENT" msgstr "" #. type: It -#: badwolf.1:70 +#: goodwolf.1:70 #, no-wrap -msgid "Ev BADWOLF_L10N" +msgid "Ev GOODWOLF_L10N" msgstr "" #. type: Plain text -#: badwolf.1:76 +#: goodwolf.1:76 msgid "" "A colon-separated list in the form lang_COUNTRY where lang is in ISO-639 and " "COUNTRY in ISO-3166. For example E<.Ic " -"BADWOLF_L10N=\"en_GB:fr_FR:de_DE\">. When this variable isn't set, spelling " -"isn't activated. A more generic variable name is also intended to be used " -"in the future." +"GOODWOLF_L10N=\"en_GB:fr_FR:de_DE\">. When this variable isn't set, " +"spelling isn't activated. A more generic variable name is also intended to " +"be used in the future." msgstr "" #. type: Plain text -#: badwolf.1:81 +#: goodwolf.1:81 msgid "" "To get the list of supported dictionaries execute E<.Ic enchant-lsmod-2 " "-list-dicts> or before enchant 2.0: E<.Ic enchant-lsmod -list-dicts>" msgstr "" #. type: Sh -#: badwolf.1:82 +#: goodwolf.1:82 #, no-wrap msgid "FILES" msgstr "" #. type: Plain text -#: badwolf.1:88 +#: goodwolf.1:88 msgid "" "The following paths are using E<.Xr sh 1> syntax to correctly support XDG " "Base Directory Specification, you can use the E<.Xr echo 1> command to check " @@ -341,13 +341,13 @@ msgid "" msgstr "" #. type: It -#: badwolf.1:90 +#: goodwolf.1:90 #, no-wrap -msgid "Pa ${XDG_CONFIG_HOME:-$HOME/.config}/badwolf/content-filters.json" +msgid "Pa ${XDG_CONFIG_HOME:-$HOME/.config}/goodwolf/content-filters.json" msgstr "" #. type: Plain text -#: badwolf.1:93 +#: goodwolf.1:93 msgid "" "WebKit-specific content-filter file, this allows to block unwanted content " "(ads, nagware, ...). For some introductory information about the format " @@ -355,23 +355,23 @@ msgid "" msgstr "" #. type: Plain text -#: badwolf.1:98 +#: goodwolf.1:98 msgid "For a converter using AblockPlus-style filters, try:" msgstr "" #. type: Plain text -#: badwolf.1:101 +#: goodwolf.1:101 msgid "For a ready-to-use file (that you should update periodically), try:" msgstr "" #. type: It -#: badwolf.1:102 +#: goodwolf.1:102 #, no-wrap -msgid "Pa ${XDG_CACHE_HOME:-$HOME/.cache}/badwolf/filters" +msgid "Pa ${XDG_CACHE_HOME:-$HOME/.cache}/goodwolf/filters" msgstr "" #. type: Plain text -#: badwolf.1:105 +#: goodwolf.1:105 msgid "" "This is where the compiled filters are stored, the file(s) in it are " "automatically generated and so shouldn't be edited. Documented here only " @@ -379,13 +379,13 @@ msgid "" msgstr "" #. type: It -#: badwolf.1:105 +#: goodwolf.1:105 #, no-wrap -msgid "Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/bookmarks.xbel" +msgid "Pa ${XDG_DATA_HOME:-$HOME/.local/share}/goodwolf/bookmarks.xbel" msgstr "" #. type: Plain text -#: badwolf.1:110 +#: goodwolf.1:110 msgid "" "XBEL (XML Bookmark Exchange Language) file, known to be currently supported " "by: E<.Xr elinks 1>, E<.Xr konqueror 1>, E<.Xr kbookmarkeditor 1 . Doing a " @@ -394,28 +394,28 @@ msgid "" msgstr "" #. type: Plain text -#: badwolf.1:112 +#: goodwolf.1:112 msgid "For more information about this format see:" msgstr "" #. type: Plain text -#: badwolf.1:115 +#: goodwolf.1:115 msgid "For an example XBEL file see:" msgstr "" #. type: It -#: badwolf.1:116 +#: goodwolf.1:116 #, no-wrap -msgid "Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/webkit-web-extension/" +msgid "Pa ${XDG_DATA_HOME:-$HOME/.local/share}/goodwolf/webkit-web-extension/" msgstr "" #. type: Plain text -#: badwolf.1:118 +#: goodwolf.1:118 msgid "Directory containing the" msgstr "" #. type: Plain text -#: badwolf.1:121 +#: goodwolf.1:121 msgid "" "to be loaded into E<.Nm . Note: They aren't the JavaScript-based " "Web-Extensions supported by Firefox or Chrome, but native code in shared " @@ -423,37 +423,37 @@ msgid "" msgstr "" #. type: Plain text -#: badwolf.1:123 +#: goodwolf.1:123 msgid "Examples of useful extensions may be found at:" msgstr "" #. type: It -#: badwolf.1:124 +#: goodwolf.1:124 #, no-wrap -msgid "Pa ${DATADIR:-/usr/local/share}/badwolf/interface.css" +msgid "Pa ${DATADIR:-/usr/local/share}/goodwolf/interface.css" msgstr "" #. type: It -#: badwolf.1:125 +#: goodwolf.1:125 #, no-wrap -msgid "Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/interface.css" +msgid "Pa ${XDG_DATA_HOME:-$HOME/.local/share}/goodwolf/interface.css" msgstr "" #. GNOME can't even into doing any redirections of the few docs available #. type: Plain text -#: badwolf.1:131 +#: goodwolf.1:131 msgid "" "CSS files (respectively system and user-level) for styling E<.Nm> " "interface. See" msgstr "" #. type: Plain text -#: badwolf.1:133 +#: goodwolf.1:133 msgid "for the properties being available." msgstr "" #. type: Plain text -#: badwolf.1:139 +#: goodwolf.1:139 msgid "" "For testing your styles I would recommend using the E<.Ev " "GTK_DEBUG=interactive> environment variable on launching E<.Nm> and going to " @@ -461,28 +461,28 @@ msgid "" msgstr "" #. type: Sh -#: badwolf.1:140 +#: goodwolf.1:140 #, no-wrap msgid "AUTHORS" msgstr "" #. type: Plain text -#: badwolf.1:142 -msgid "E<.An Haelwenn (lanodan) Monnier Aq Mt contact+badwolf@hacktivis.me>" +#: goodwolf.1:142 +msgid "E<.An Haelwenn (lanodan) Monnier Aq Mt contact+goodwolf@hacktivis.me>" msgstr "" #. type: Sh -#: badwolf.1:142 +#: goodwolf.1:142 #, no-wrap msgid "BUGS" msgstr "" #. type: Plain text -#: badwolf.1:144 +#: goodwolf.1:144 msgid "You can submit contributions or tickets to" msgstr "" #. type: Plain text -#: badwolf.1:147 +#: goodwolf.1:147 msgid "with E<.Xr git-send-email 1> for patches." msgstr "" diff --git a/po/messages.pot b/po/messages.pot index 32905ff..8147786 100644 --- a/po/messages.pot +++ b/po/messages.pot @@ -74,23 +74,23 @@ msgstr "" msgid "Bookmarks: unable to parse file \"%s\"\n" msgstr "" -#: badwolf.c:1190 +#: goodwolf.c:1190 #, c-format msgid "Buildtime WebKit version: %d.%d.%d\n" msgstr "" -#: badwolf.c:497 +#: goodwolf.c:497 msgid "Continue" msgstr "" -#: badwolf.c:442 +#: goodwolf.c:442 msgid "" "Couldn't verify the TLS certificate to ensure a better security of the " "connection. You might want to verify your machine and network.\n" "\n" msgstr "" -#: badwolf.c:113 +#: goodwolf.c:113 msgid "Crashed" msgstr "" @@ -98,31 +98,31 @@ msgstr "" msgid "Download starting…" msgstr "" -#: badwolf.c:465 +#: goodwolf.c:465 msgid "Error: Some unknown error occurred validating the certificate.\n" msgstr "" -#: badwolf.c:446 +#: goodwolf.c:446 msgid "Error: The X509 Certificate Authority is unknown.\n" msgstr "" -#: badwolf.c:459 +#: goodwolf.c:459 msgid "Error: The certificate has been revoked.\n" msgstr "" -#: badwolf.c:456 +#: goodwolf.c:456 msgid "Error: The certificate has expired. Check your system's clock.\n" msgstr "" -#: badwolf.c:462 +#: goodwolf.c:462 msgid "Error: The certificate is considered to be insecure.\n" msgstr "" -#: badwolf.c:453 +#: goodwolf.c:453 msgid "Error: The certificate isn't valid yet. Check your system's clock.\n" msgstr "" -#: badwolf.c:449 +#: goodwolf.c:449 msgid "Error: The given identity doesn't match the expected one.\n" msgstr "" @@ -133,99 +133,99 @@ msgid "" "Runtime WebKit version: %d.%d.%d" msgstr "" -#: badwolf.c:1013 +#: goodwolf.c:1013 msgid "New tab" msgstr "" -#: badwolf.c:1260 +#: goodwolf.c:1260 msgid "Open new tab" msgstr "" -#: badwolf.c:117 +#: goodwolf.c:117 msgid "Out of Memory" msgstr "" -#: badwolf.c:1188 +#: goodwolf.c:1188 #, c-format msgid "Running Badwolf version: %s\n" msgstr "" -#: badwolf.c:1195 +#: goodwolf.c:1195 #, c-format msgid "Runtime WebKit version: %d.%d.%d\n" msgstr "" -#: badwolf.c:494 +#: goodwolf.c:494 #, c-format msgid "TLS Error for %s." msgstr "" -#: badwolf.c:497 +#: goodwolf.c:497 msgid "Temporarily Add Exception" msgstr "" -#: badwolf.c:731 +#: goodwolf.c:731 msgid "Toggle javascript" msgstr "" -#: badwolf.c:736 +#: goodwolf.c:736 msgid "Toggle loading images automatically" msgstr "" -#: badwolf.c:121 +#: goodwolf.c:121 msgid "Unknown Crash" msgstr "" -#: badwolf.c:734 +#: goodwolf.c:734 msgid "_IMG" msgstr "" -#: badwolf.c:729 +#: goodwolf.c:729 msgid "_JS" msgstr "" -#: badwolf.c:1091 +#: goodwolf.c:1216 #, c-format -msgid "badwolf: content-filter loaded, adding to content-manager…\n" +msgid "content-filters file set to: %s\n" msgstr "" -#: badwolf.c:1111 badwolf.c:1118 +#: goodwolf.c:1091 #, c-format -msgid "badwolf: failed to compile content-filters.json, err: [%d] %s\n" +msgid "goodwolf: content-filter loaded, adding to content-manager…\n" msgstr "" -#: badwolf.c:1079 badwolf.c:1084 +#: goodwolf.c:1111 goodwolf.c:1118 #, c-format -msgid "badwolf: failed to load content-filter, err: [%d] %s\n" +msgid "goodwolf: failed to compile content-filters.json, err: [%d] %s\n" msgstr "" -#: badwolf.c:1216 +#: goodwolf.c:1079 goodwolf.c:1084 #, c-format -msgid "content-filters file set to: %s\n" +msgid "goodwolf: failed to load content-filter, err: [%d] %s\n" msgstr "" -#: badwolf.c:901 +#: goodwolf.c:901 msgid "search in current page" msgstr "" -#: badwolf.c:112 +#: goodwolf.c:112 msgid "the web process crashed.\n" msgstr "" -#: badwolf.c:116 +#: goodwolf.c:116 msgid "the web process exceeded the memory limit.\n" msgstr "" -#: badwolf.c:120 +#: goodwolf.c:120 msgid "the web process terminated for an unknown reason.\n" msgstr "" -#: badwolf.c:1202 +#: goodwolf.c:1202 #, c-format msgid "webkit-web-extension directory set to: %s\n" msgstr "" #. TRANSLATOR Ignore this entry. Done for forcing Unicode in xgettext. -#: badwolf.c:1325 +#: goodwolf.c:1325 msgid "ø" msgstr "" diff --git a/uri.c b/uri.c index c026c28..77aaf82 100644 --- a/uri.c +++ b/uri.c @@ -9,7 +9,7 @@ #include /* access() */ const gchar * -badwolf_ensure_uri_scheme(const gchar *text, gboolean try_file) +goodwolf_ensure_uri_scheme(const gchar *text, gboolean try_file) { const gchar *fallback = "about:blank"; char *path = NULL; diff --git a/uri.h b/uri.h index cef50b4..16619aa 100644 --- a/uri.h +++ b/uri.h @@ -2,7 +2,7 @@ #define URI_H_INCLUDED #include -/* badwolf_ensure_uri_scheme: tries to add a scheme on a pseudo-URL missing a scheme +/* goodwolf_ensure_uri_scheme: tries to add a scheme on a pseudo-URL missing a scheme * - gchar text: pseudo-URL missing a scheme * - gboolean try_file: when TRUE check try first if it can be a file:// path * @@ -13,5 +13,5 @@ * In the end use the fallback (`http://` for now, might get configuration), * might get some safeguard. */ -const gchar *badwolf_ensure_uri_scheme(const gchar *text, gboolean try_file); +const gchar *goodwolf_ensure_uri_scheme(const gchar *text, gboolean try_file); #endif /* URI_H_INCLUDED */ diff --git a/uri_test.c b/uri_test.c index 47fda73..cb6ea9c 100644 --- a/uri_test.c +++ b/uri_test.c @@ -8,7 +8,7 @@ #include static void -badwolf_ensure_uri_scheme_test(void) +goodwolf_ensure_uri_scheme_test(void) { const gchar *fallback = "about:blank"; @@ -37,16 +37,16 @@ badwolf_ensure_uri_scheme_test(void) {"http://example.org", "example.org", TRUE}, {"http://", "http://", FALSE}, {"http://", "http://", TRUE}, - {"http://badwolf.c", "badwolf.c", FALSE} // + {"http://goodwolf.c", "goodwolf.c", FALSE} // }; for(size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { - g_info("badwolf_ensure_uri_scheme(\"%s\", %s)", + g_info("goodwolf_ensure_uri_scheme(\"%s\", %s)", cases[i].text, cases[i].try_file ? "TRUE" : "FALSE"); - const gchar *got = badwolf_ensure_uri_scheme(cases[i].text, cases[i].try_file); + const gchar *got = goodwolf_ensure_uri_scheme(cases[i].text, cases[i].try_file); if(g_strcmp0(got, cases[i].expect) != 0) { @@ -60,7 +60,7 @@ main(int argc, char *argv[]) { g_test_init(&argc, &argv, NULL); - g_test_add_func("/badwolf_ensure_uri_scheme/test", badwolf_ensure_uri_scheme_test); + g_test_add_func("/goodwolf_ensure_uri_scheme/test", goodwolf_ensure_uri_scheme_test); return g_test_run(); } diff --git a/usr.bin.badwolf b/usr.bin.badwolf deleted file mode 100644 index 861ee9f..0000000 --- a/usr.bin.badwolf +++ /dev/null @@ -1,81 +0,0 @@ -# BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser -# Copyright © 2019-2021 Badwolf Authors -# SPDX-License-Identifier: BSD-3-Clause -# -# Made on Gentoo Linux with PREFIX=/usr -#include - -/usr/bin/badwolf { - #include - #include - #include - #include - #include - - /usr/bin/badwolf mr, - /usr/bin/bwrap Cx, - /usr/libexec/webkit2gtk-4.0/WebKitNetworkProcess Cx, - /usr/libexec/webkit2gtk-4.0/WebKitWebProcess Cx, - - owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/fd/ r, - - owner @{HOME}/.local/share/badwolf/ r, - owner @{HOME}/.local/share/badwolf/** r, - - deny @{HOME}/.local/share/webkitgtk/** rwmlk, - - / r, - /** r, - - #include - - profile /usr/libexec/webkit2gtk-4.0/WebKitNetworkProcess { - #include - #include - #include - #include - - network inet stream, - network inet6 stream, - - /usr/libexec/webkit2gtk-4.0/WebKitNetworkProcess mr, - /** r, - owner /** w, - } - - profile /usr/libexec/webkit2gtk-4.0/WebKitWebProcess { - #include - #include - #include - #include - #include - #include - #include - #include - - /usr/libexec/webkit2gtk-4.0/WebKitWebProcess mr, - - owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/fd/ r, - - /etc/passwd r, - /etc/group r, - /etc/nsswitch.conf r, - /dev/ r, - - owner @{HOME}/.local/share/badwolf/webkit-web-extension/ r, - owner @{HOME}/.local/share/badwolf/webkit-web-extension/** mr, - } - - profile /usr/bin/bwrap { - #include - - deny capability sys_admin, - - /usr/bin/bwrap mr, - @{PROC}/sys/kernel/overflowuid r, - @{PROC}/sys/kernel/overflowgid r, - owner @{PROC}/@{pid}/fd/ r, - } -} diff --git a/usr.bin.goodwolf b/usr.bin.goodwolf new file mode 100644 index 0000000..0b7f556 --- /dev/null +++ b/usr.bin.goodwolf @@ -0,0 +1,81 @@ +# BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser +# Copyright © 2019-2021 Badwolf Authors +# SPDX-License-Identifier: BSD-3-Clause +# +# Made on Gentoo Linux with PREFIX=/usr +#include + +/usr/bin/goodwolf { + #include + #include + #include + #include + #include + + /usr/bin/goodwolf mr, + /usr/bin/bwrap Cx, + /usr/libexec/webkit2gtk-4.0/WebKitNetworkProcess Cx, + /usr/libexec/webkit2gtk-4.0/WebKitWebProcess Cx, + + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/fd/ r, + + owner @{HOME}/.local/share/goodwolf/ r, + owner @{HOME}/.local/share/goodwolf/** r, + + deny @{HOME}/.local/share/webkitgtk/** rwmlk, + + / r, + /** r, + + #include + + profile /usr/libexec/webkit2gtk-4.0/WebKitNetworkProcess { + #include + #include + #include + #include + + network inet stream, + network inet6 stream, + + /usr/libexec/webkit2gtk-4.0/WebKitNetworkProcess mr, + /** r, + owner /** w, + } + + profile /usr/libexec/webkit2gtk-4.0/WebKitWebProcess { + #include + #include + #include + #include + #include + #include + #include + #include + + /usr/libexec/webkit2gtk-4.0/WebKitWebProcess mr, + + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/fd/ r, + + /etc/passwd r, + /etc/group r, + /etc/nsswitch.conf r, + /dev/ r, + + owner @{HOME}/.local/share/goodwolf/webkit-web-extension/ r, + owner @{HOME}/.local/share/goodwolf/webkit-web-extension/** mr, + } + + profile /usr/bin/bwrap { + #include + + deny capability sys_admin, + + /usr/bin/bwrap mr, + @{PROC}/sys/kernel/overflowuid r, + @{PROC}/sys/kernel/overflowgid r, + owner @{PROC}/@{pid}/fd/ r, + } +} -- cgit v1.3.1-23-gd82d