summaryrefslogtreecommitdiffstats
path: root/src/config
diff options
context:
space:
mode:
authorPatrick McDermott <pj@pehjota.net>2017-11-01 12:54:02 (EDT)
committer Patrick McDermott <pj@pehjota.net>2017-11-01 12:54:02 (EDT)
commit8e1209d464ba70a76c5fb92977ec6bfb70c8f9fb (patch)
treedfc87a4d9d963ac7337065ca933c17afb3634745 /src/config
parenta76657b8513d73ad48f5daaf414689aa23c8bb55 (diff)
downloadmarquee-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.c529
-rw-r--r--src/config/config.h93
-rw-r--r--src/config/settings.c439
-rw-r--r--src/config/settings.h74
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 */