/*
* 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;
}
}
/* 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);
}