/* * 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 . */ #include "settings.h" #include #include #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; default: g_assert_not_reached(); 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); }