diff options
| Commit | 762114dcc99d4e70a0472813ff41f77e44277bb8 (patch) | |
|---|---|---|
| Author | 2021-04-19 22:31:58 +0200 | |
| Committer | 2021-04-19 22:31:58 +0200 | |
| Files | 57387ef745ab5022bb34c74d304e9c32dbd7331d /badwolf.c | |
| goodwolf-1.1.0.tar goodwolf-1.1.0.tar.gz goodwolf-1.1.0.zip | ||
| Parent | 680ca3102df72264022babbea5003fb98d8e5189 (diff) | |
| Parent | 4abd7044fda92b4d3dcb4774ff8d5f7772987b6a (diff) | |
Merge branch 'release-1.1' into missy for 1.1.0 v1.1.0
1 files changed, 184 insertions, 30 deletions
| -rw-r--r-- | badwolf.c | 214 |
@@ -1,25 +1,30 @@ // BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser -// Copyright © 2019-2020 Badwolf Authors <https://hacktivis.me/projects/badwolf> +// Copyright © 2019-2021 Badwolf Authors <https://hacktivis.me/projects/badwolf> // SPDX-License-Identifier: BSD-3-Clause #include "badwolf.h" +#include "bookmarks.h" #include "config.h" #include "downloads.h" #include "keybindings.h" #include "uri.h" +#include <assert.h> #include <glib/gi18n.h> /* _() and other internationalization/localization helpers */ #include <libsoup/soup.h> /* soup* */ #include <locale.h> /* LC_* */ -#include <stdio.h> /* perror(), fprintf() */ +#include <stdio.h> /* perror(), fprintf(), snprintf() */ #include <stdlib.h> /* malloc() */ #include <unistd.h> /* access() */ -gchar *web_extensions_directory; 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 WebViewCb_close(WebKitWebView *webView, gpointer user_data); static gboolean WebViewCb_web_process_terminated(WebKitWebView *webView, WebKitWebProcessTerminationReason reason, @@ -66,6 +71,7 @@ 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) @@ -126,10 +132,37 @@ WebViewCb_notify__uri(WebKitWebView *webView, GParamSpec *pspec, gpointer user_d return TRUE; } +static char * +fmt_context_id(uint64_t num, char *out) +{ + const char alpha_digits[27] = {" ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; + char buf[66] = {'\0'}; + int i, len = 0; + + // Get 0 = 'A' instead of 0 = '' and 1 = 'A' + num++; + + buf[len++] = ' '; + buf[len++] = ':'; + do + { + buf[len++] = alpha_digits[num % 26]; + } while(num /= 26); + + for(i = 0; len > 0; i++) + out[i] = buf[--len]; + + return out; +} + GtkWidget * badwolf_new_tab_box(const gchar *title, struct Client *browser) { (void)browser; + char context_id_str[7] = ""; + + fmt_context_id(browser->context_id, context_id_str); + GtkWidget *tab_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_widget_set_name(tab_box, "browser__tabbox"); GtkWidget *close = @@ -137,6 +170,8 @@ badwolf_new_tab_box(const gchar *title, struct Client *browser) gtk_widget_set_name(close, "browser__tabbox__close"); GtkWidget *label = gtk_label_new(title); gtk_widget_set_name(label, "browser__tabbox__label"); + GtkWidget *context_label = gtk_label_new(context_id_str); + gtk_widget_set_name(context_label, "browser__tabbox__context_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"); @@ -151,7 +186,9 @@ badwolf_new_tab_box(const gchar *title, struct Client *browser) gtk_label_set_ellipsize(GTK_LABEL(label), BADWOLF_TAB_LABEL_ELLIPSIZE); gtk_label_set_single_line_mode(GTK_LABEL(label), TRUE); + gtk_label_set_single_line_mode(GTK_LABEL(context_label), TRUE); + gtk_box_pack_start(GTK_BOX(tab_box), context_label, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(tab_box), playing, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(tab_box), label, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(tab_box), close, FALSE, FALSE, 0); @@ -280,10 +317,15 @@ WebViewCb_create(WebKitWebView *related_web_view, gpointer user_data) { (void)navigation_action; - struct Window *window = (struct Window *)user_data; - struct Client *browser = new_browser(window, NULL, related_web_view); + 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; - if(badwolf_new_tab(GTK_NOTEBOOK(window->notebook), browser, FALSE) < 0) + 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; @@ -423,7 +465,9 @@ web_contextCb_download_started(WebKitWebContext *web_context, { (void)web_context; struct Client *browser = (struct Client *)user_data; - struct Download *download = malloc(sizeof(struct Client)); + struct Download *download = malloc(sizeof(struct Download)); + + assert(webkit_download); if(download != NULL) { @@ -515,7 +559,7 @@ printCb_clicked(GtkButton *print, gpointer user_data) WebKitPrintOperation *print_operation = webkit_print_operation_new(browser->webView); - webkit_print_operation_run_dialog(print_operation, GTK_WINDOW(browser->window)); + webkit_print_operation_run_dialog(print_operation, GTK_WINDOW(browser->window->main_window)); } static gboolean @@ -577,16 +621,19 @@ widgetCb_drop_button3_event(GtkWidget *widget, GdkEvent *event, gpointer user_da } struct Client * -new_browser(struct Window *window, const gchar *target_url, WebKitWebView *related_web_view) +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, (related_web_view == NULL)); + 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->box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + 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); @@ -625,14 +672,27 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat browser->statuslabel = gtk_label_new(NULL); gtk_widget_set_name(browser->statuslabel, "browser__statuslabel"); - setenv("GTK_THEME", ":light", 0); + if(old_browser == NULL) + { + WebKitWebsiteDataManager *website_data_manager = webkit_website_data_manager_new_ephemeral(); + webkit_website_data_manager_set_itp_enabled(website_data_manager, TRUE); - WebKitWebContext *web_context = webkit_web_context_new_ephemeral(); - webkit_web_context_set_sandbox_enabled(web_context, TRUE); - webkit_web_context_set_process_model(web_context, - WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES); + 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_web_extensions_directory(web_context, web_extensions_directory); + 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); + } badwolf_l10n = getenv("BADWOLF_L10N"); @@ -656,12 +716,17 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat "web-context", web_context, "related-view", - related_web_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"); - g_object_unref(web_context); + if(old_browser == NULL) + { + g_object_unref(web_context); + } g_object_unref(settings); gtk_box_pack_start( @@ -720,6 +785,15 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat 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); @@ -787,7 +861,7 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat "notify::estimated-load-progress", G_CALLBACK(WebViewCb_notify__estimated_load_progress), browser); - g_signal_connect(browser->webView, "create", G_CALLBACK(WebViewCb_create), window); + 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); @@ -801,12 +875,6 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat browser); g_signal_connect(browser->webView, "load-changed", G_CALLBACK(WebViewCb_load_changed), browser); - /* signals for WebView's WebContext */ - g_signal_connect(G_OBJECT(web_context), - "download-started", - G_CALLBACK(web_contextCb_download_started), - browser); - /* signals for search widget */ g_signal_connect(browser->search, "next-match", G_CALLBACK(SearchEntryCb_next__match), browser); g_signal_connect( @@ -818,7 +886,7 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat /* signals for box container */ g_signal_connect(browser->box, "key-press-event", G_CALLBACK(boxCb_key_press_event), browser); - if(related_web_view == NULL) webkit_web_view_load_uri(browser->webView, target_url); + if(old_browser == NULL) webkit_web_view_load_uri(browser->webView, target_url); return browser; } @@ -887,10 +955,75 @@ notebookCb_switch__page(GtkNotebook *notebook, GtkWidget *page, guint page_num, 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); + } +} + int main(int argc, char *argv[]) { - struct Window *window = &(struct Window){NULL, NULL, NULL, NULL}; + struct Window *window = &(struct Window){NULL, NULL, NULL, NULL, NULL, NULL}; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, DATADIR "/locale"); bind_textdomain_codeset(PACKAGE, "UTF-8"); @@ -914,10 +1047,29 @@ main(int argc, char *argv[]) g_build_filename(g_get_user_data_dir(), "badwolf", "webkit-web-extension", NULL); fprintf(stderr, _("webkit-web-extension directory set to: %s\n"), web_extensions_directory); + bookmarks_completion_model = bookmarks_completion_init(); + g_object_ref(bookmarks_completion_model); + window->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); window->notebook = gtk_notebook_new(); window->new_tab = gtk_button_new_from_icon_name("tab-new-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); - window->downloads_tab = badwolf_downloads_tab_new(); + 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); @@ -981,6 +1133,8 @@ main(int argc, char *argv[]) gtk_main(); + g_object_unref(bookmarks_completion_model); + #if 0 /* TRANSLATOR Ignore this entry. Done for forcing Unicode in xgettext. */ _("ø"); |