diff options
author | Patrick McDermott <pj@pehjota.net> | 2017-11-01 12:54:02 (EDT) |
---|---|---|
committer | Patrick McDermott <pj@pehjota.net> | 2017-11-01 12:54:02 (EDT) |
commit | 8e1209d464ba70a76c5fb92977ec6bfb70c8f9fb (patch) | |
tree | dfc87a4d9d963ac7337065ca933c17afb3634745 /src/config | |
parent | a76657b8513d73ad48f5daaf414689aa23c8bb55 (diff) | |
download | marquee-8e1209d464ba70a76c5fb92977ec6bfb70c8f9fb.zip marquee-8e1209d464ba70a76c5fb92977ec6bfb70c8f9fb.tar.gz marquee-8e1209d464ba70a76c5fb92977ec6bfb70c8f9fb.tar.bz2 |
src/config.[ch], src/settings.[ch]: Move under src/config/
Diffstat (limited to 'src/config')
-rw-r--r-- | src/config/config.c | 529 | ||||
-rw-r--r-- | src/config/config.h | 93 | ||||
-rw-r--r-- | src/config/settings.c | 439 | ||||
-rw-r--r-- | src/config/settings.h | 74 |
4 files changed, 1135 insertions, 0 deletions
diff --git a/src/config/config.c b/src/config/config.c new file mode 100644 index 0000000..8b46fb1 --- /dev/null +++ b/src/config/config.c @@ -0,0 +1,529 @@ +/* + * Application configuration + * + * Copyright (C) 2017 Patrick McDermott + * + * This file is part of Marquee. + * + * Marquee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Marquee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Marquee. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "config.h" + +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +struct MqConfig { + gchar *profile; + gchar *file_name; + GKeyFile *key_file; + gboolean types_and_cbs_set; + GHashTable *types_and_cbs; +}; + +enum type { + TYPE_BOOLEAN, + TYPE_INTEGER, + TYPE_DOUBLE, + TYPE_STRING, +}; + +union callback { + MqConfigBooleanCallback boolean_cb; + MqConfigIntegerCallback integer_cb; + MqConfigDoubleCallback double_cb; + MqConfigStringCallback string_cb; +}; + +struct callbacks { + union callback cb; + gpointer user_data; + struct callbacks *next; +}; + +struct item { + enum type type; + struct callbacks *callbacks; +}; + +#define SET_BOOL(NAME, VALUE) mq_config_set_boolean(config, NAME, VALUE) +#define SET_INT( NAME, VALUE) mq_config_set_integer(config, NAME, VALUE) +#define SET_DBL( NAME, VALUE) mq_config_set_double (config, NAME, VALUE) +#define SET_STR( NAME, VALUE) mq_config_set_string (config, NAME, VALUE) +#define SET_STRL(NAME, VALUE) mq_config_set_string (config, NAME, VALUE) + +static void +set_defaults(MqConfig *config) +{ + config->types_and_cbs_set = FALSE; + + /* General -> Web Browsing */ + SET_STR ("tabs.new", "home"); + SET_STR ("tabs.home", ""); /* TODO */ + SET_BOOL("tabs.background", TRUE); + SET_BOOL("tabs.warn-on-close", TRUE); + + /* General -> Navigation and Accessibility */ + SET_BOOL("navigation.smooth-scrolling", TRUE); + SET_BOOL("navigation.tabbing", TRUE); + SET_BOOL("navigation.caret", FALSE); + SET_BOOL("navigation.spatial", FALSE); + + /* General -> Spell Checking */ + SET_BOOL("spell.enable", TRUE); + SET_STRL("spell.langs", "en_US"); // TODO + + /* General -> Miscellaneous */ + SET_BOOL("display.textarea.resize.enable", TRUE); + SET_BOOL("devtools.enable", TRUE); + + /* General -> Compatibility */ + SET_STR ("compatibility.user-agent", "default"); + SET_BOOL("compatibility.quirks", TRUE); + + /* Display -> Fonts */ + SET_STR ("font.family.default", "sans-serif"); + SET_STR ("font.family.monospace", "monospace"); + SET_STR ("font.family.serif", "serif"); + SET_STR ("font.family.sans-serif", "sans-serif"); + SET_STR ("font.family.cursive", "serif"); + SET_STR ("font.family.fantasy", "serif"); + SET_STR ("font.family.pictograph", "serif"); + SET_INT ("font.size.default", 16); + SET_INT ("font.size.monospace-default", 13); + SET_INT ("font.size.minimum", 0); + + /* Display -> Languages */ + SET_STRL("intl.accept-languages", "en-us"); // TODO + SET_STR ("intl.default-charset", "iso-8859-1"); //^ + + /* Display -> Zoom */ + SET_DBL ("zoom.default", 1.00); + SET_BOOL("zoom.text-only", FALSE); + + /* Permissions -> General */ + SET_BOOL("permissions.images.auto-load", TRUE); + SET_BOOL("permissions.images.favicons.override", FALSE); + SET_BOOL("permissions.java.enable", TRUE); + SET_BOOL("permissions.javascript.enable", TRUE); + SET_BOOL("permissions.plugins.enable", TRUE); + + /* Permissions -> JavaScript */ + SET_BOOL("permissions.javascript.open-windows", FALSE); + SET_BOOL("permissions.javascript.fullscreen", TRUE); + SET_BOOL("permissions.javascript.modal-dialogs", FALSE); + SET_BOOL("permissions.javascript.clipboard", FALSE); + + /* Permissions -> Data Storage */ + SET_BOOL("permissions.javascript.database", TRUE); + SET_BOOL("permissions.javascript.storage", TRUE); + SET_BOOL("permissions.appcache", TRUE); + + /* Permissions -> Graphics and Multimedia */ + SET_BOOL("canvas.acceleration.enable", FALSE); + SET_BOOL("permissions.javascript.webgl", FALSE); + SET_BOOL("permissions.javascript.audio", FALSE); + SET_BOOL("media.autoplay", TRUE); + SET_BOOL("media.force-fullscreen", FALSE); + SET_BOOL("permissions.javascript.mediastream.enable", FALSE); + SET_BOOL("permissions.javascript.mediasource.enable", FALSE); + + /* Security and Privacy -> History */ + SET_BOOL("privacy.private-browsing.enabled", FALSE); + SET_BOOL("privacy.remember.history", TRUE); + SET_BOOL("privacy.remember.downloads", TRUE); + + /* Security and Privacy -> Cookies */ + SET_STR ("cookies.accept", "always"); + + /* Security and Privacy -> Security */ + SET_BOOL("security.xss-auditor.enable", TRUE); + + /* Security and Privacy -> Network */ + SET_BOOL("dns.prefetch.enable", FALSE); + + /* Hidden window state preferences */ + SET_BOOL("window.maximized", FALSE); + SET_INT ("window.width", 1024); + SET_INT ("window.height", 768); + + /* Hidden directory preferences */ + SET_STR ("directories.open-file", ""); + SET_STR ("directories.downloads", + g_get_user_special_dir(G_USER_DIRECTORY_DOWNLOAD)); + + config->types_and_cbs_set = TRUE; +} + +#undef SET_BOOL +#undef SET_INT +#undef SET_DBL +#undef SET_STR +#undef SET_STRL + +MqConfig * +mq_config_new(const gchar *profile) +{ + MqConfig *config; + + config = malloc(sizeof(*config)); + + config->profile = g_strdup(profile); + config->file_name = g_build_filename(g_get_user_config_dir(), + PACKAGE, profile, "config", NULL); + config->key_file = g_key_file_new(); + config->types_and_cbs = g_hash_table_new(g_str_hash, g_int_equal); + set_defaults(config); + + return config; +} + +gboolean +mq_config_load(MqConfig *config) +{ + gchar *profile_dir; + + profile_dir = g_build_filename(g_get_user_config_dir(), PACKAGE, + config->profile, NULL); + g_mkdir_with_parents(profile_dir, 0700); + g_free(profile_dir); + + /* TODO: Handle parsing and ENOENT errors differently? */ + return g_key_file_load_from_file(config->key_file, config->file_name, + G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, NULL); +} + +gboolean +mq_config_save(MqConfig *config) +{ + /* TODO: Handle GFileError? */ + return g_key_file_save_to_file(config->key_file, config->file_name, + NULL); +} + +static void +split_name(const gchar *name, gchar **group, gchar **key) +{ + *group = g_strdup(name); + *key = strchr(*group, '.'); + *(key[0]) = '\0'; + ++*key; +} + +gboolean +mq_config_get_boolean(MqConfig *config, const gchar *name) +{ + gchar *group; + gchar *key; + gboolean value; + + split_name(name, &group, &key); + + /* TODO: Handle value parsing errors? */ + value = g_key_file_get_boolean(config->key_file, group, key, NULL); + + g_free(group); + + return value; +} + +gint +mq_config_get_integer(MqConfig *config, const gchar *name) +{ + gchar *group; + gchar *key; + gint value; + + split_name(name, &group, &key); + + /* TODO: Handle value parsing errors? */ + value = g_key_file_get_integer(config->key_file, group, key, NULL); + + g_free(group); + + return value; +} + +gdouble +mq_config_get_double(MqConfig *config, const gchar *name) +{ + gchar *group; + gchar *key; + gdouble value; + + split_name(name, &group, &key); + + /* TODO: Handle value parsing errors? */ + value = g_key_file_get_double(config->key_file, group, key, NULL); + + g_free(group); + + return value; +} + +gchar * +mq_config_get_string(MqConfig *config, const gchar *name) +{ + gchar *group; + gchar *key; + gchar *value; + + split_name(name, &group, &key); + + /* TODO: Handle value parsing errors? */ + value = g_key_file_get_string(config->key_file, group, key, NULL); + + g_free(group); + + return value; +} + +gchar ** +mq_config_get_string_list(MqConfig *config, const gchar *name) +{ + gchar *group; + gchar *key; + gchar **value; + + split_name(name, &group, &key); + + /* TODO: Handle value parsing errors? */ + value = g_key_file_get_string_list(config->key_file, group, key, NULL, + NULL); + + g_free(group); + + return value; +} + +static void +set_type_or_run_callbacks(MqConfig *config, const gchar *name, + gconstpointer value, enum type type) +{ + struct item *item; + struct callbacks *cbs; + + if (!config->types_and_cbs_set) { + item = g_malloc(sizeof(*item)); + item->type = type; + item->callbacks = NULL; + g_hash_table_insert(config->types_and_cbs, g_strdup(name), + item); + } else { + item = g_hash_table_lookup(config->types_and_cbs, name); + for (cbs = item->callbacks; cbs; cbs = cbs->next) { + switch (item->type) { + case TYPE_BOOLEAN: + cbs->cb.boolean_cb(config, name, + *((const gboolean *) value), + cbs->user_data); + break; + case TYPE_INTEGER: + cbs->cb.integer_cb(config, name, + *((const gint *) value), + cbs->user_data); + break; + case TYPE_DOUBLE: + cbs->cb.double_cb(config, name, + *((const gdouble *) value), + cbs->user_data); + break; + case TYPE_STRING: + cbs->cb.string_cb(config, name, + (const gchar *) value, + cbs->user_data); + break; + } + } + } +} + +void +mq_config_set_boolean(MqConfig *config, const gchar *name, gboolean value) +{ + gchar *group; + gchar *key; + + split_name(name, &group, &key); + + g_key_file_set_boolean(config->key_file, group, key, value); + + g_free(group); + + set_type_or_run_callbacks(config, name, &value, TYPE_BOOLEAN); +} + +void +mq_config_set_integer(MqConfig *config, const gchar *name, gint value) +{ + gchar *group; + gchar *key; + + split_name(name, &group, &key); + + g_key_file_set_integer(config->key_file, group, key, value); + + g_free(group); + + set_type_or_run_callbacks(config, name, &value, TYPE_INTEGER); +} + +void +mq_config_set_double(MqConfig *config, const gchar *name, gdouble value) +{ + gchar *group; + gchar *key; + + split_name(name, &group, &key); + + g_key_file_set_double(config->key_file, group, key, value); + + g_free(group); + + set_type_or_run_callbacks(config, name, &value, TYPE_DOUBLE); +} + +void +mq_config_set_string(MqConfig *config, const gchar *name, const gchar *value) +{ + gchar *group; + gchar *key; + + split_name(name, &group, &key); + + g_key_file_set_string(config->key_file, group, key, value); + + g_free(group); + + set_type_or_run_callbacks(config, name, value, TYPE_STRING); +} + +gboolean +mq_config_set(MqConfig *config, const gchar *name, const gchar *value) +{ + struct item *item; + gint integer_value; + gdouble double_value; + gchar *endptr; + + item = g_hash_table_lookup(config->types_and_cbs, name); + g_assert(item); + + switch (item->type) { + case TYPE_BOOLEAN: + /* value is "on" or "off" (as implemented in + * mq_html_input_checkbox()). */ + mq_config_set_boolean(config, name, + value[1] == 'n' ? TRUE : FALSE); + return TRUE; + case TYPE_INTEGER: + integer_value = strtol(value, &endptr, 10); + if (*endptr != '\0') { + return FALSE; + } + mq_config_set_integer(config, name, integer_value); + return TRUE; + case TYPE_DOUBLE: + double_value = strtod(value, &endptr); + if (*endptr != '\0') { + return FALSE; + } + mq_config_set_double(config, name, double_value); + return TRUE; + case TYPE_STRING: + mq_config_set_string(config, name, value); + return TRUE; + } + + g_assert_not_reached(); + return FALSE; +} + +void +mq_config_notify_boolean(MqConfig *config, const gchar *name, + MqConfigBooleanCallback callback, gpointer user_data) +{ + struct item *item; + struct callbacks *cbs; + + item = g_hash_table_lookup(config->types_and_cbs, name); + g_assert(item->type == TYPE_BOOLEAN); + + cbs = g_malloc(sizeof(*cbs)); + cbs->cb.boolean_cb = callback; + cbs->user_data = user_data; + cbs->next = item->callbacks; + + item->callbacks = cbs; +} + +void +mq_config_notify_integer(MqConfig *config, const gchar *name, + MqConfigIntegerCallback callback, gpointer user_data) +{ + struct item *item; + struct callbacks *cbs; + + item = g_hash_table_lookup(config->types_and_cbs, name); + g_assert(item->type == TYPE_INTEGER); + + cbs = g_malloc(sizeof(*cbs)); + cbs->cb.integer_cb = callback; + cbs->user_data = user_data; + cbs->next = item->callbacks; + + item->callbacks = cbs; +} + +void +mq_config_notify_double(MqConfig *config, const gchar *name, + MqConfigDoubleCallback callback, gpointer user_data) +{ + struct item *item; + struct callbacks *cbs; + + item = g_hash_table_lookup(config->types_and_cbs, name); + g_assert(item->type == TYPE_DOUBLE); + + cbs = g_malloc(sizeof(*cbs)); + cbs->cb.double_cb = callback; + cbs->user_data = user_data; + cbs->next = item->callbacks; + + item->callbacks = cbs; +} + +void +mq_config_notify_string(MqConfig *config, const gchar *name, + MqConfigStringCallback callback, gpointer user_data) +{ + struct item *item; + struct callbacks *cbs; + + item = g_hash_table_lookup(config->types_and_cbs, name); + g_assert(item->type == TYPE_STRING); + + cbs = g_malloc(sizeof(*cbs)); + cbs->cb.string_cb = callback; + cbs->user_data = user_data; + cbs->next = item->callbacks; + + item->callbacks = cbs; +} diff --git a/src/config/config.h b/src/config/config.h new file mode 100644 index 0000000..93af5f8 --- /dev/null +++ b/src/config/config.h @@ -0,0 +1,93 @@ +/* + * Application configuration + * + * Copyright (C) 2017 Patrick McDermott + * + * This file is part of Marquee. + * + * Marquee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Marquee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Marquee. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MQ_CONFIG_H +#define MQ_CONFIG_H + +typedef struct MqConfig MqConfig; + +#include <glib.h> + +typedef void (*MqConfigBooleanCallback)(MqConfig *, + const gchar *, const gboolean, gpointer); +typedef void (*MqConfigIntegerCallback)(MqConfig *, + const gchar *, const gint, gpointer); +typedef void (*MqConfigDoubleCallback)(MqConfig *, + const gchar *, const gdouble, gpointer); +typedef void (*MqConfigStringCallback)(MqConfig *, + const gchar *, const gchar *, gpointer); + +MqConfig * +mq_config_new(const gchar *profile); + +gboolean +mq_config_load(MqConfig *config); + +gboolean +mq_config_save(MqConfig *config); + +gboolean +mq_config_get_boolean(MqConfig *config, const gchar *name); + +gint +mq_config_get_integer(MqConfig *config, const gchar *name); + +gdouble +mq_config_get_double(MqConfig *config, const gchar *name); + +gchar * +mq_config_get_string(MqConfig *config, const gchar *name); + +gchar ** +mq_config_get_string_list(MqConfig *config, const gchar *name); + +void +mq_config_set_boolean(MqConfig *config, const gchar *name, gboolean value); + +void +mq_config_set_integer(MqConfig *config, const gchar *name, gint value); + +void +mq_config_set_double(MqConfig *config, const gchar *name, gdouble value); + +void +mq_config_set_string(MqConfig *config, const gchar *name, const gchar *value); + +gboolean +mq_config_set(MqConfig *config, const gchar *name, const gchar *value); + +void +mq_config_notify_boolean(MqConfig *config, const gchar *name, + MqConfigBooleanCallback callback, gpointer user_data); + +void +mq_config_notify_integer(MqConfig *config, const gchar *name, + MqConfigIntegerCallback callback, gpointer user_data); + +void +mq_config_notify_double(MqConfig *config, const gchar *name, + MqConfigDoubleCallback callback, gpointer user_data); + +void +mq_config_notify_string(MqConfig *config, const gchar *name, + MqConfigStringCallback callback, gpointer user_data); + +#endif diff --git a/src/config/settings.c b/src/config/settings.c new file mode 100644 index 0000000..a271613 --- /dev/null +++ b/src/config/settings.c @@ -0,0 +1,439 @@ +/* + * Web view settings + * + * Copyright (C) 2017 Patrick McDermott + * + * This file is part of Marquee. + * + * Marquee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Marquee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Marquee. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "settings.h" + +#include <glib.h> +#include <webkit2/webkit2.h> + +#include "config.h" + +enum mapping_type { + MAP_BOOL, + MAP_BOOL_N, + MAP_INT, + /* MAP_DBL, */ + MAP_STR, + /* MAP_STRL, */ +}; + +struct mapping { + enum mapping_type type; + const gchar *mq_name; + const gchar *wk_name; +}; + +static struct mapping mappings[] = { + /* General -> Navigation and Accessibility */ + {MAP_BOOL, "navigation.smooth-scrolling", + "enable-smooth-scrolling"}, + {MAP_BOOL, "navigation.tabbing", + "enable-tabs-to-links"}, + {MAP_BOOL, "navigation.caret", + "enable-caret-browsing"}, + {MAP_BOOL, "navigation.spatial", + "enable-spatial-navigation"}, + + /* General -> Miscellaneous */ + {MAP_BOOL, "display.textarea.resize.enable", + "enable-resizable-text-areas"}, + {MAP_BOOL, "devtools.enable", + "enable-developer-extras"}, + + /* General -> Compatibility */ + // compatibility.user-agent + {MAP_BOOL, "compatibility.quirks", + "enable-site-specific-quirks"}, + + /* Display -> Fonts */ + {MAP_STR, "font.family.default", + "default-font-family"}, + {MAP_STR, "font.family.monospace", + "monospace-font-family"}, + {MAP_STR, "font.family.serif", + "serif-font-family"}, + {MAP_STR, "font.family.sans-serif", + "sans-serif-font-family"}, + {MAP_STR, "font.family.cursive", + "cursive-font-family"}, + {MAP_STR, "font.family.fantasy", + "fantasy-font-family"}, + {MAP_STR, "font.family.pictograph", + "pictograph-font-family"}, + {MAP_INT, "font.size.default", + "default-font-size"}, + {MAP_INT, "font.size.monospace-default", + "default-monospace-font-size"}, + {MAP_INT, "font.size.minimum", + "minimum-font-size"}, + + /* Display -> Languages */ + {MAP_STR, "intl.default-charset", + "default-charset"}, + + /* Display -> Zoom */ + {MAP_BOOL, "zoom.text-only", + "zoom-text-only"}, + + /* Permissions -> General */ + {MAP_BOOL, "permissions.images.auto-load", + "auto-load-images"}, + {MAP_BOOL, "permissions.images.favicons.override", + "load-icons-ignoring-image-load-setting"}, + {MAP_BOOL, "permissions.java.enable", + "enable-java"}, + {MAP_BOOL, "permissions.javascript.enable", + "enable-javascript"}, + {MAP_BOOL, "permissions.plugins.enable", + "enable-plugins"}, + + /* Permissions -> JavaScript */ + {MAP_BOOL, "permissions.javascript.open-windows", + "javascript-can-open-windows-automatically"}, + {MAP_BOOL, "permissions.javascript.fullscreen", + "enable-fullscreen"}, + {MAP_BOOL, "permissions.javascript.modal-dialogs", + "allow-modal-dialogs"}, + {MAP_BOOL, "permissions.javascript.clipboard", + "javascript-can-access-clipboard"}, + + /* Permissions -> Data Storage */ + {MAP_BOOL, "permissions.javascript.database", + "enable-html5-database"}, + {MAP_BOOL, "permissions.javascript.storage", + "enable-html5-local-storage"}, + {MAP_BOOL, "permissions.appcache", + "enable-offline-web-application-cache"}, + + /* Permissions -> Graphics and Multimedia */ + {MAP_BOOL, "canvas.acceleration.enable", + "enable-accelerated-2d-canvas"}, + {MAP_BOOL, "permissions.javascript.webgl", + "enable-webgl"}, + {MAP_BOOL, "permissions.javascript.audio", + "enable-webaudio"}, + {MAP_BOOL_N, "media.autoplay", + "media-playback-requires-user-gesture"}, + {MAP_BOOL_N, "media.force-fullscreen", + "media-playback-allows-inline"}, + {MAP_BOOL, "permissions.javascript.mediastream.enable", + "enable-media-stream"}, + {MAP_BOOL, "permissions.javascript.mediasource.enable", + "enable-mediasource"}, + + /* Security and Privacy -> History */ + {MAP_BOOL, "privacy.private-browsing.enabled", + "enable-private-browsing"}, + + /* Security and Privacy -> Security */ + {MAP_BOOL, "security.xss-auditor.enable", + "enable-xss-auditor"}, + + /* Security and Privacy -> Network */ + {MAP_BOOL, "dns.prefetch.enable", + "enable-dns-prefetching"}, +}; + +static GHashTable *mappings_table = NULL; + +static gboolean true_value = TRUE; + +struct _MqSettings { + WebKitSettings parent_instance; + WebKitWebContext *web_context; + GHashTable *overrides; +}; + +struct _MqSettingsClass { + WebKitSettingsClass parent_class; +}; + +G_DEFINE_TYPE(MqSettings, mq_settings, WEBKIT_TYPE_SETTINGS) + +static void +init_mappings_table(void) +{ + gsize i; + + if (mappings_table) { + return; + } + + mappings_table = g_hash_table_new(g_str_hash, g_str_equal); + + for (i = 0; i < sizeof(mappings) / sizeof(mappings[0]); ++i) { + g_hash_table_insert(mappings_table, + g_strdup(mappings[i].mq_name), &mappings[i]); + } +} + +static void +mq_settings_class_init(MqSettingsClass G_GNUC_UNUSED *klass) +{ +} + +static void +mq_settings_init(MqSettings *settings) +{ + init_mappings_table(); + + settings->overrides = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); +} + +MqSettings * +mq_settings_new(void) +{ + return g_object_new(MQ_TYPE_SETTINGS, NULL); +} + +void +mq_settings_set_web_context(MqSettings *settings, WebKitWebContext *web_context) +{ + settings->web_context = web_context; +} + +#define is_neg(NAME) \ + (((struct mapping *) g_hash_table_lookup(mappings_table, \ + NAME))->type == MAP_BOOL_N) +#define map_name(NAME) \ + (((struct mapping *) g_hash_table_lookup(mappings_table, \ + NAME))->wk_name) + +static void +set_bool(MqSettings *settings, const gchar *name, const gboolean value) +{ + GValue g_value = G_VALUE_INIT; + + g_value_init(&g_value, G_TYPE_BOOLEAN); + g_value_set_boolean(&g_value, is_neg(name) ? !value : value); + g_object_set_property(G_OBJECT(settings), map_name(name), &g_value); +} + +static void +set_int(MqSettings *settings, const gchar *name, const gint value) +{ + GValue g_value = G_VALUE_INIT; + + g_value_init(&g_value, G_TYPE_INT); + g_value_set_int(&g_value, value); + g_object_set_property(G_OBJECT(settings), map_name(name), &g_value); +} + +static void +set_str(MqSettings *settings, const gchar *name, const gchar *value) +{ + GValue g_value = G_VALUE_INIT; + + g_value_init(&g_value, G_TYPE_STRING); + g_value_set_static_string(&g_value, value); + g_object_set_property(G_OBJECT(settings), map_name(name), &g_value); +} + +void +mq_settings_override_bool(MqSettings *settings, const gchar *name, + const gboolean value) +{ + g_hash_table_insert(settings->overrides, g_strdup(name), &true_value); + set_bool(settings, name, value); +} + +void +mq_settings_override_int(MqSettings *settings, const gchar *name, + const gint value) +{ + g_hash_table_insert(settings->overrides, g_strdup(name), &true_value); + set_int(settings, name, value); +} + +void +mq_settings_override_str(MqSettings *settings, const gchar *name, + const gchar *value) +{ + g_hash_table_insert(settings->overrides, g_strdup(name), &true_value); + set_str(settings, name, value); +} + +static void +bool_cb(MqConfig G_GNUC_UNUSED *config, const gchar *name, + const gboolean value, MqSettings *settings) +{ + set_bool(settings, name, value); +} + +static void +bool_n_cb(MqConfig G_GNUC_UNUSED *config, const gchar *name, + const gboolean value, MqSettings *settings) +{ + set_bool(settings, name, value); +} + +static void +int_cb(MqConfig G_GNUC_UNUSED *config, const gchar *name, + const gint value, MqSettings *settings) +{ + set_int(settings, name, value); +} + +static void +str_cb(MqConfig G_GNUC_UNUSED *config, const gchar *name, + const gchar *value, MqSettings *settings) +{ + set_str(settings, name, value); +} + +static void +wc_spell_checking_enabled_cb(MqConfig G_GNUC_UNUSED *config, + const gchar G_GNUC_UNUSED *name, const gboolean value, + WebKitWebContext *web_context) +{ + webkit_web_context_set_spell_checking_enabled(web_context, value); +} + +static void +wc_spell_checking_languages_cb(MqConfig *config, const gchar *name, + const gchar G_GNUC_UNUSED *value, WebKitWebContext *web_context) +{ + webkit_web_context_set_spell_checking_languages(web_context, + (const gchar * const *) mq_config_get_string_list(config, + name)); +} + +static void +wc_preferred_languages_cb(MqConfig *config, const gchar *name, + const gchar G_GNUC_UNUSED *value, WebKitWebContext *web_context) +{ + webkit_web_context_set_preferred_languages(web_context, + (const gchar * const *) mq_config_get_string_list(config, + name)); +} + +static void +cm_accept_policy_cb(MqConfig G_GNUC_UNUSED *config, + const gchar G_GNUC_UNUSED *name, const gchar *value, + WebKitCookieManager *cookie_manager) +{ + if (g_strcmp0(value, "always") == 0) { + webkit_cookie_manager_set_accept_policy(cookie_manager, + WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + } else if (g_strcmp0(value, "never") == 0) { + webkit_cookie_manager_set_accept_policy(cookie_manager, + WEBKIT_COOKIE_POLICY_ACCEPT_NEVER); + } else if (g_strcmp0(value, "no-third-party") == 0) { + webkit_cookie_manager_set_accept_policy(cookie_manager, + WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY); + } else { + g_assert_not_reached(); + } +} + +void +mq_settings_connect_config(MqSettings *settings, MqConfig *config) +{ + gsize i; + WebKitCookieManager *cookie_manager; + + /* mq_settings_set_web_context() must be called first. */ + g_assert(settings->web_context); + + cookie_manager = webkit_web_context_get_cookie_manager( + settings->web_context); + + for (i = 0; i < sizeof(mappings) / sizeof(mappings[0]); ++i) { + if (g_hash_table_lookup(settings->overrides, + mappings[i].mq_name)) { + continue; + } + switch (mappings[i].type) { + case MAP_BOOL: + mq_config_notify_boolean(config, + mappings[i].mq_name, + (MqConfigBooleanCallback) bool_cb, + settings); + bool_cb(config, mappings[i].mq_name, + mq_config_get_boolean(config, + mappings[i].mq_name), + settings); + break; + case MAP_BOOL_N: + mq_config_notify_boolean(config, + mappings[i].mq_name, + (MqConfigBooleanCallback) bool_n_cb, + settings); + bool_n_cb(config, mappings[i].mq_name, + mq_config_get_boolean(config, + mappings[i].mq_name), + settings); + break; + case MAP_INT: + mq_config_notify_integer(config, + mappings[i].mq_name, + (MqConfigIntegerCallback) int_cb, + settings); + int_cb(config, mappings[i].mq_name, + mq_config_get_integer(config, + mappings[i].mq_name), + settings); + break; + case MAP_STR: + mq_config_notify_string(config, + mappings[i].mq_name, + (MqConfigStringCallback) str_cb, + settings); + str_cb(config, mappings[i].mq_name, + mq_config_get_string(config, + mappings[i].mq_name), + settings); + break; + } + } + + /* The overrides table is no longer needed. */ + g_hash_table_unref(settings->overrides); + + /* General -> Spell Checking */ + mq_config_notify_boolean(config, "spell.enable", + (MqConfigBooleanCallback) wc_spell_checking_enabled_cb, + settings->web_context); + wc_spell_checking_enabled_cb(config, "spell.enable", + mq_config_get_boolean(config, "spell.enable"), + settings->web_context); + mq_config_notify_string(config, "spell.langs", + (MqConfigStringCallback) wc_spell_checking_languages_cb, + settings->web_context); + wc_spell_checking_languages_cb(config, "spell.langs", NULL, + settings->web_context); + + /* Display -> Languages */ + mq_config_notify_string(config, "intl.accept-languages", + (MqConfigStringCallback) wc_preferred_languages_cb, + settings->web_context); + wc_preferred_languages_cb(config, "intl.accept-languages", NULL, + settings->web_context); + + /* Security and Privacy -> Cookies */ + mq_config_notify_string(config, "cookies.accept", + (MqConfigStringCallback) cm_accept_policy_cb, + cookie_manager); + cm_accept_policy_cb(config, "cookies.accept", + mq_config_get_string(config, "cookies.accept"), + cookie_manager); +} diff --git a/src/config/settings.h b/src/config/settings.h new file mode 100644 index 0000000..2424c59 --- /dev/null +++ b/src/config/settings.h @@ -0,0 +1,74 @@ +/* + * Web view settings + * + * Copyright (C) 2017 Patrick McDermott + * + * This file is part of Marquee. + * + * Marquee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Marquee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Marquee. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MQ_SETTINGS_H +#define MQ_SETTINGS_H + +typedef struct _MqSettings MqSettings; +typedef struct _MqSettingsClass MqSettingsClass; + +#include <glib.h> +#include <webkit2/webkit2.h> + +#include "config.h" + +G_BEGIN_DECLS + +#define MQ_TYPE_SETTINGS (mq_settings_get_type()) +#define MQ_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + MQ_TYPE_SETTINGS, MqSettings)) +#define MQ_IS_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + MQ_TYPE_SETTINGS)) +#define MQ_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + MQ_TYPE_SETTINGS, MqSettingsClass)) +#define MQ_IS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), \ + MQ_TYPE_SETTINGS)) +#define MQ_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + MQ_TYPE_SETTINGS, MqSettingsClass)) + +GType +mq_settings_get_type(void); + +MqSettings * +mq_settings_new(void); + +void +mq_settings_set_web_context(MqSettings *settings, + WebKitWebContext *web_context); + +void +mq_settings_override_bool(MqSettings *settings, const gchar *name, + const gboolean value); + +void +mq_settings_override_int(MqSettings *settings, const gchar *name, + const gint value); + +void +mq_settings_override_str(MqSettings *settings, const gchar *name, + const gchar *value); + +void +mq_settings_connect_config(MqSettings *settings, MqConfig *config); + +G_END_DECLS + +#endif /* MQ_SETTINGS_H */ |