Faster Base64-concatenating CSS and stylesheet URI support
It is important to retain user-stylesheet-uri separate from the value set at runtime and restore it to the config file. Fixes: https://bugs.launchpad.net/midori/+bug/883879
This commit is contained in:
parent
fc2bac2e01
commit
23f90e821a
2 changed files with 100 additions and 27 deletions
|
@ -202,6 +202,19 @@ settings_save_to_file (MidoriWebSettings* settings,
|
||||||
{
|
{
|
||||||
gchar* string;
|
gchar* string;
|
||||||
const gchar* def_string = G_PARAM_SPEC_STRING (pspec)->default_value;
|
const gchar* def_string = G_PARAM_SPEC_STRING (pspec)->default_value;
|
||||||
|
if (!strcmp (property, "user-stylesheet-uri"))
|
||||||
|
{
|
||||||
|
const gchar* user_stylesheet_uri = g_object_get_data (G_OBJECT (settings), property);
|
||||||
|
if (user_stylesheet_uri)
|
||||||
|
{
|
||||||
|
g_key_file_set_string (key_file, "settings", property,
|
||||||
|
user_stylesheet_uri);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_key_file_remove_key (key_file, "settings", property, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
g_object_get (settings, property, &string, NULL);
|
g_object_get (settings, property, &string, NULL);
|
||||||
if (!string)
|
if (!string)
|
||||||
string = g_strdup ("");
|
string = g_strdup ("");
|
||||||
|
|
|
@ -91,6 +91,7 @@ struct _MidoriWebSettings
|
||||||
gboolean enforce_font_family;
|
gboolean enforce_font_family;
|
||||||
gboolean flash_window_on_bg_tabs;
|
gboolean flash_window_on_bg_tabs;
|
||||||
gchar* user_stylesheet_uri;
|
gchar* user_stylesheet_uri;
|
||||||
|
gchar* user_stylesheet_uri_cached;
|
||||||
GHashTable* user_stylesheets;
|
GHashTable* user_stylesheets;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1122,7 +1123,7 @@ midori_web_settings_init (MidoriWebSettings* web_settings)
|
||||||
web_settings->http_proxy = NULL;
|
web_settings->http_proxy = NULL;
|
||||||
web_settings->open_popups_in_tabs = TRUE;
|
web_settings->open_popups_in_tabs = TRUE;
|
||||||
web_settings->kinetic_scrolling = TRUE;
|
web_settings->kinetic_scrolling = TRUE;
|
||||||
web_settings->user_stylesheet_uri = NULL;
|
web_settings->user_stylesheet_uri = web_settings->user_stylesheet_uri_cached = NULL;
|
||||||
web_settings->user_stylesheets = NULL;
|
web_settings->user_stylesheets = NULL;
|
||||||
|
|
||||||
g_signal_connect (web_settings, "notify::default-encoding",
|
g_signal_connect (web_settings, "notify::default-encoding",
|
||||||
|
@ -1147,6 +1148,7 @@ midori_web_settings_finalize (GObject* object)
|
||||||
katze_assign (web_settings->http_proxy, NULL);
|
katze_assign (web_settings->http_proxy, NULL);
|
||||||
katze_assign (web_settings->ident_string, NULL);
|
katze_assign (web_settings->ident_string, NULL);
|
||||||
katze_assign (web_settings->user_stylesheet_uri, NULL);
|
katze_assign (web_settings->user_stylesheet_uri, NULL);
|
||||||
|
katze_assign (web_settings->user_stylesheet_uri_cached, NULL);
|
||||||
if (web_settings->user_stylesheets != NULL)
|
if (web_settings->user_stylesheets != NULL)
|
||||||
g_hash_table_destroy (web_settings->user_stylesheets);
|
g_hash_table_destroy (web_settings->user_stylesheets);
|
||||||
|
|
||||||
|
@ -1273,6 +1275,14 @@ generate_ident_string (MidoriWebSettings* web_settings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_web_settings_process_stylesheets (MidoriWebSettings* settings,
|
||||||
|
gint delta_len);
|
||||||
|
|
||||||
|
static void
|
||||||
|
base64_space_pad (gchar* base64,
|
||||||
|
guint len);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
midori_web_settings_set_property (GObject* object,
|
midori_web_settings_set_property (GObject* object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
|
@ -1535,15 +1545,25 @@ midori_web_settings_set_property (GObject* object,
|
||||||
web_settings->flash_window_on_bg_tabs = g_value_get_boolean (value);
|
web_settings->flash_window_on_bg_tabs = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
case PROP_USER_STYLESHEET_URI:
|
case PROP_USER_STYLESHEET_URI:
|
||||||
if ((web_settings->user_stylesheet_uri = g_value_dup_string (value)))
|
|
||||||
{
|
{
|
||||||
gchar* css = g_strdup_printf ("@import url(\"%s\"\n);",
|
gint old_len = web_settings->user_stylesheet_uri_cached
|
||||||
web_settings->user_stylesheet_uri);
|
? strlen (web_settings->user_stylesheet_uri_cached) : 0;
|
||||||
midori_web_settings_add_style (web_settings, "user-stylesheet-uri", css);
|
gint new_len = 0;
|
||||||
g_free (css);
|
if ((web_settings->user_stylesheet_uri = g_value_dup_string (value)))
|
||||||
|
{
|
||||||
|
gchar* import = g_strdup_printf ("@import url(\"%s\");",
|
||||||
|
web_settings->user_stylesheet_uri);
|
||||||
|
gchar* encoded = g_base64_encode ((const guchar*)import, strlen (import));
|
||||||
|
new_len = strlen (encoded);
|
||||||
|
base64_space_pad (encoded, new_len);
|
||||||
|
g_free (import);
|
||||||
|
katze_assign (web_settings->user_stylesheet_uri_cached, encoded);
|
||||||
|
}
|
||||||
|
/* Make original user-stylesheet-uri available to main.c */
|
||||||
|
g_object_set_data (G_OBJECT (web_settings), "user-stylesheet-uri",
|
||||||
|
web_settings->user_stylesheet_uri);
|
||||||
|
midori_web_settings_process_stylesheets (web_settings, new_len - old_len);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
midori_web_settings_remove_style (web_settings, "user-stylesheet-uri");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
@ -1807,7 +1827,8 @@ midori_web_settings_get_property (GObject* object,
|
||||||
g_value_set_boolean (value, web_settings->flash_window_on_bg_tabs);
|
g_value_set_boolean (value, web_settings->flash_window_on_bg_tabs);
|
||||||
break;
|
break;
|
||||||
case PROP_USER_STYLESHEET_URI:
|
case PROP_USER_STYLESHEET_URI:
|
||||||
g_value_set_string (value, web_settings->user_stylesheet_uri);
|
g_value_take_string (value, katze_object_get_string (web_settings,
|
||||||
|
"WebKitWebSettings::user-stylesheet-uri"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
@ -1834,29 +1855,54 @@ midori_web_settings_new (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
midori_web_settings_process_stylesheets (MidoriWebSettings* settings)
|
midori_web_settings_process_stylesheets (MidoriWebSettings* settings,
|
||||||
|
gint delta_len)
|
||||||
{
|
{
|
||||||
GHashTableIter it;
|
GHashTableIter it;
|
||||||
GString* css = g_string_new ("");
|
GString* css;
|
||||||
gchar* base64;
|
|
||||||
gchar* encoded;
|
gchar* encoded;
|
||||||
gpointer key;
|
|
||||||
gpointer value;
|
gpointer value;
|
||||||
|
static guint length = 0;
|
||||||
|
|
||||||
g_hash_table_iter_init (&it, settings->user_stylesheets);
|
g_return_if_fail ((gint)length >= -delta_len);
|
||||||
while (g_hash_table_iter_next (&it, &key, &value))
|
|
||||||
g_string_append_printf (css, "%s\n", (const gchar*) value);
|
length += delta_len;
|
||||||
|
|
||||||
|
/* Precalculate size to avoid re-allocations */
|
||||||
|
css = g_string_sized_new (length);
|
||||||
|
|
||||||
|
if (settings->user_stylesheet_uri_cached != NULL)
|
||||||
|
g_string_append (css, settings->user_stylesheet_uri_cached);
|
||||||
|
|
||||||
|
if (settings->user_stylesheets != NULL)
|
||||||
|
{
|
||||||
|
g_hash_table_iter_init (&it, settings->user_stylesheets);
|
||||||
|
while (g_hash_table_iter_next (&it, NULL, &value))
|
||||||
|
g_string_append (css, (gchar*)value);
|
||||||
|
}
|
||||||
|
|
||||||
/* data: uri prefix from Source/WebCore/page/Page.cpp:700 in WebKit */
|
/* data: uri prefix from Source/WebCore/page/Page.cpp:700 in WebKit */
|
||||||
encoded = g_base64_encode ((guchar*)css->str, css->len);
|
encoded = g_strconcat ("data:text/css;charset=utf-8;base64,", css->str, NULL);
|
||||||
base64 = g_strdup_printf ("data:text/css;charset=utf-8;base64,%s", encoded);
|
g_object_set (G_OBJECT (settings), "WebKitWebSettings::user-stylesheet-uri", encoded, NULL);
|
||||||
g_object_set (settings, "WebKitWebSettings::user-stylesheet-uri", base64, NULL);
|
|
||||||
|
|
||||||
g_free (encoded);
|
g_free (encoded);
|
||||||
g_free (base64);
|
|
||||||
g_string_free (css, TRUE);
|
g_string_free (css, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
base64_space_pad (gchar* base64,
|
||||||
|
guint len)
|
||||||
|
{
|
||||||
|
/* Replace '=' padding at the end with encoded spaces
|
||||||
|
so WebKit will accept concatenations to this string */
|
||||||
|
if (len > 2 && base64[len - 2] == '=')
|
||||||
|
{
|
||||||
|
base64[len - 3] += 2;
|
||||||
|
base64[len - 2] = 'A';
|
||||||
|
}
|
||||||
|
if (len > 1 && base64[len - 1] == '=')
|
||||||
|
base64[len - 1] = 'g';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* midori_web_settings_add_style:
|
* midori_web_settings_add_style:
|
||||||
* @rule_id: a static string identifier
|
* @rule_id: a static string identifier
|
||||||
|
@ -1871,15 +1917,24 @@ midori_web_settings_add_style (MidoriWebSettings* settings,
|
||||||
const gchar* rule_id,
|
const gchar* rule_id,
|
||||||
const gchar* style)
|
const gchar* style)
|
||||||
{
|
{
|
||||||
|
gchar* base64;
|
||||||
|
guint len;
|
||||||
|
|
||||||
g_return_if_fail (MIDORI_IS_WEB_SETTINGS (settings));
|
g_return_if_fail (MIDORI_IS_WEB_SETTINGS (settings));
|
||||||
g_return_if_fail (rule_id != NULL);
|
g_return_if_fail (rule_id != NULL);
|
||||||
g_return_if_fail (style != NULL);
|
g_return_if_fail (style != NULL);
|
||||||
|
|
||||||
|
len = strlen (style);
|
||||||
|
base64 = g_base64_encode ((const guchar*)style, len);
|
||||||
|
len = ((len + 2) / 3) * 4;
|
||||||
|
base64_space_pad (base64, len);
|
||||||
|
|
||||||
if (settings->user_stylesheets == NULL)
|
if (settings->user_stylesheets == NULL)
|
||||||
settings->user_stylesheets = g_hash_table_new_full (g_str_hash, NULL,
|
settings->user_stylesheets = g_hash_table_new_full (g_str_hash, NULL,
|
||||||
NULL, g_free);
|
NULL, g_free);
|
||||||
g_hash_table_insert (settings->user_stylesheets, (gchar*)rule_id, g_strdup (style));
|
|
||||||
midori_web_settings_process_stylesheets (settings);
|
g_hash_table_insert (settings->user_stylesheets, (gchar*)rule_id, base64);
|
||||||
|
midori_web_settings_process_stylesheets (settings, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1894,13 +1949,18 @@ void
|
||||||
midori_web_settings_remove_style (MidoriWebSettings* settings,
|
midori_web_settings_remove_style (MidoriWebSettings* settings,
|
||||||
const gchar* rule_id)
|
const gchar* rule_id)
|
||||||
{
|
{
|
||||||
|
gchar* str;
|
||||||
|
|
||||||
g_return_if_fail (MIDORI_IS_WEB_SETTINGS (settings));
|
g_return_if_fail (MIDORI_IS_WEB_SETTINGS (settings));
|
||||||
g_return_if_fail (rule_id != NULL);
|
g_return_if_fail (rule_id != NULL);
|
||||||
|
|
||||||
if (settings->user_stylesheets != NULL)
|
if (settings->user_stylesheets != NULL)
|
||||||
{
|
{
|
||||||
g_hash_table_remove (settings->user_stylesheets, rule_id);
|
if ((str = g_hash_table_lookup (settings->user_stylesheets, rule_id)))
|
||||||
midori_web_settings_process_stylesheets (settings);
|
{
|
||||||
|
guint len = strlen (str);
|
||||||
|
g_hash_table_remove (settings->user_stylesheets, rule_id);
|
||||||
|
midori_web_settings_process_stylesheets (settings, -len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue