summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2013-02-24 13:15:05 +0000
committerVincent Sanders <vince@kyllikki.org>2013-02-24 16:08:37 +0000
commitcc7f45898bdde2793ee17f99ea4cf058250a16b5 (patch)
tree9077addadd48f6a665fe8b0cae56bbbd69867756
parentbba74b7a0b414809e29d8b19978db1996a8822ac (diff)
downloadnetsurf-cc7f45898bdde2793ee17f99ea4cf058250a16b5.tar.gz
netsurf-cc7f45898bdde2793ee17f99ea4cf058250a16b5.tar.bz2
refactor stylesheet handling to separate object from within html rendering
-rw-r--r--Makefile.sources6
-rw-r--r--render/html.c682
-rw-r--r--render/html.h9
-rw-r--r--render/html_css.c678
-rw-r--r--render/html_internal.h18
-rw-r--r--utils/corestrings.c3
-rw-r--r--utils/corestrings.h1
7 files changed, 729 insertions, 668 deletions
diff --git a/Makefile.sources b/Makefile.sources
index 550c563bc..6810915f9 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -13,9 +13,9 @@ S_CSS := css.c dump.c internal.c select.c utils.c
S_RENDER := box.c box_construct.c box_normalise.c box_textarea.c \
font.c form.c \
- html.c html_script.c html_interaction.c html_redraw.c \
- html_forms.c imagemap.c layout.c list.c search.c table.c \
- textplain.c
+ html.c html_css.c html_script.c html_interaction.c \
+ html_redraw.c html_forms.c imagemap.c layout.c list.c \
+ search.c table.c textplain.c
S_UTILS := base64.c corestrings.c filename.c filepath.c hashtable.c \
libdom.c locale.c log.c messages.c nsurl.c talloc.c url.c \
diff --git a/render/html.c b/render/html.c
index aeb5a5b73..37178de9c 100644
--- a/render/html.c
+++ b/render/html.c
@@ -72,48 +72,6 @@ static const char *html_types[] = {
/* forward declared functions */
static void html_object_refresh(void *p);
-/* pre-interned character set */
-static lwc_string *html_charset;
-
-static nsurl *html_default_stylesheet_url;
-static nsurl *html_adblock_stylesheet_url;
-static nsurl *html_quirks_stylesheet_url;
-static nsurl *html_user_stylesheet_url;
-
-static nserror css_error_to_nserror(css_error error)
-{
- switch (error) {
- case CSS_OK:
- return NSERROR_OK;
-
- case CSS_NOMEM:
- return NSERROR_NOMEM;
-
- case CSS_BADPARM:
- return NSERROR_BAD_PARAMETER;
-
- case CSS_INVALID:
- return NSERROR_INVALID;
-
- case CSS_FILENOTFOUND:
- return NSERROR_NOT_FOUND;
-
- case CSS_NEEDDATA:
- return NSERROR_NEED_DATA;
-
- case CSS_BADCHARSET:
- return NSERROR_BAD_ENCODING;
-
- case CSS_EOF:
- case CSS_IMPORTS_PENDING:
- case CSS_PROPERTY_NOT_SET:
- default:
- break;
- }
- return NSERROR_CSS;
-}
-
-
static void html_destroy_objects(html_content *html)
{
while (html->object_list != NULL) {
@@ -218,8 +176,6 @@ void html_finish_conversion(html_content *c)
union content_msg_data msg_data;
dom_exception exc; /* returned by libdom functions */
dom_node *html;
- uint32_t i;
- css_error css_ret;
nserror error;
/* Bail out if we've been aborted */
@@ -229,55 +185,14 @@ void html_finish_conversion(html_content *c)
return;
}
- /* check that the base stylesheet loaded; layout fails without it */
- if (c->stylesheets[STYLESHEET_BASE].data.external == NULL) {
- content_broadcast_errorcode(&c->base, NSERROR_CSS_BASE);
- content_set_error(&c->base);
- return;
- }
-
- /* Create selection context */
- css_ret = css_select_ctx_create(ns_realloc, c, &c->select_ctx);
- if (css_ret != CSS_OK) {
- content_broadcast_errorcode(&c->base,
- css_error_to_nserror(css_ret));
+ /* create new css selection context */
+ error = html_css_new_selection_context(c, &c->select_ctx);
+ if (error != NSERROR_OK) {
+ content_broadcast_errorcode(&c->base, error);
content_set_error(&c->base);
return;
}
- /* Add sheets to it */
- for (i = STYLESHEET_BASE; i != c->stylesheet_count; i++) {
- const struct html_stylesheet *hsheet = &c->stylesheets[i];
- css_stylesheet *sheet;
- css_origin origin = CSS_ORIGIN_AUTHOR;
-
- if (i < STYLESHEET_USER)
- origin = CSS_ORIGIN_UA;
- else if (i < STYLESHEET_START)
- origin = CSS_ORIGIN_USER;
-
- if (hsheet->type == HTML_STYLESHEET_EXTERNAL &&
- hsheet->data.external != NULL) {
- sheet = nscss_get_stylesheet(hsheet->data.external);
- } else if (hsheet->type == HTML_STYLESHEET_INTERNAL) {
- sheet = hsheet->data.internal->sheet;
- } else {
- sheet = NULL;
- }
-
- if (sheet != NULL) {
- css_ret = css_select_ctx_append_sheet(c->select_ctx,
- sheet,
- origin,
- CSS_MEDIA_SCREEN);
- if (css_ret != CSS_OK) {
- content_broadcast_errorcode(&c->base,
- css_error_to_nserror(css_ret));
- content_set_error(&c->base);
- return;
- }
- }
- }
/* fire a simple event named load at the Document's Window
* object, but with its target set to the Document object (and
@@ -311,492 +226,6 @@ void html_finish_conversion(html_content *c)
dom_node_unref(html);
}
-/**
- * Callback for fetchcache() for linked stylesheets.
- */
-
-static nserror
-html_convert_css_callback(hlcache_handle *css,
- const hlcache_event *event,
- void *pw)
-{
- html_content *parent = pw;
- unsigned int i;
- struct html_stylesheet *s;
-
- /* Find sheet */
- for (i = 0, s = parent->stylesheets;
- i != parent->stylesheet_count; i++, s++) {
- if (s->type == HTML_STYLESHEET_EXTERNAL &&
- s->data.external == css)
- break;
- }
-
- assert(i != parent->stylesheet_count);
-
- switch (event->type) {
- case CONTENT_MSG_LOADING:
- break;
-
- case CONTENT_MSG_READY:
- break;
-
- case CONTENT_MSG_DONE:
- LOG(("done stylesheet slot %d '%s'", i,
- nsurl_access(hlcache_handle_get_url(css))));
- parent->base.active--;
- LOG(("%d fetches active", parent->base.active));
- break;
-
- case CONTENT_MSG_ERROR:
- LOG(("stylesheet %s failed: %s",
- nsurl_access(hlcache_handle_get_url(css)),
- event->data.error));
- hlcache_handle_release(css);
- s->data.external = NULL;
- parent->base.active--;
- LOG(("%d fetches active", parent->base.active));
- content_add_error(&parent->base, "?", 0);
- break;
-
- case CONTENT_MSG_STATUS:
- if (event->data.explicit_status_text == NULL) {
- /* Object content's status text updated */
- html_set_status(parent,
- content_get_status_message(css));
- content_broadcast(&parent->base, CONTENT_MSG_STATUS,
- event->data);
- } else {
- /* Object content wants to set explicit message */
- content_broadcast(&parent->base, CONTENT_MSG_STATUS,
- event->data);
- }
- break;
-
- case CONTENT_MSG_POINTER:
- /* Really don't want this to continue after the switch */
- return NSERROR_OK;
-
- default:
- assert(0);
- }
-
- if (parent->base.active == 0) {
- html_begin_conversion(parent);
- }
-
- return NSERROR_OK;
-}
-
-/**
- * Initialise core stylesheets
- *
- * \param c content structure
- * \return true on success, false if an error occurred
- */
-
-static bool html_init_stylesheets(html_content *c)
-{
- nserror ns_error;
- hlcache_child_context child;
-
- if (c->stylesheets != NULL) {
- return true; /* already initialised */
- }
-
- /* stylesheet 0 is the base style sheet,
- * stylesheet 1 is the quirks mode style sheet,
- * stylesheet 2 is the adblocking stylesheet,
- * stylesheet 3 is the user stylesheet */
- c->stylesheets = calloc(STYLESHEET_START, sizeof(struct html_stylesheet));
- if (c->stylesheets == NULL) {
- ns_error = NSERROR_NOMEM;
- goto html_find_stylesheets_no_memory;
- }
-
- c->stylesheets[STYLESHEET_BASE].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_BASE].data.external = NULL;
- c->stylesheets[STYLESHEET_QUIRKS].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_QUIRKS].data.external = NULL;
- c->stylesheets[STYLESHEET_ADBLOCK].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_ADBLOCK].data.external = NULL;
- c->stylesheets[STYLESHEET_USER].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_USER].data.external = NULL;
- c->stylesheet_count = STYLESHEET_START;
-
- child.charset = c->encoding;
- child.quirks = c->base.quirks;
-
- ns_error = hlcache_handle_retrieve(html_default_stylesheet_url, 0,
- content_get_url(&c->base), NULL,
- html_convert_css_callback, c, &child, CONTENT_CSS,
- &c->stylesheets[STYLESHEET_BASE].data.external);
- if (ns_error != NSERROR_OK)
- goto html_find_stylesheets_no_memory;
-
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- if (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL) {
- ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url,
- 0, content_get_url(&c->base), NULL,
- html_convert_css_callback, c, &child,
- CONTENT_CSS,
- &c->stylesheets[STYLESHEET_QUIRKS].data.external);
- if (ns_error != NSERROR_OK)
- goto html_find_stylesheets_no_memory;
-
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- }
-
- if (nsoption_bool(block_ads)) {
- ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url,
- 0, content_get_url(&c->base), NULL,
- html_convert_css_callback, c, &child, CONTENT_CSS,
- &c->stylesheets[STYLESHEET_ADBLOCK].
- data.external);
- if (ns_error != NSERROR_OK)
- goto html_find_stylesheets_no_memory;
-
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- }
-
- ns_error = hlcache_handle_retrieve(html_user_stylesheet_url, 0,
- content_get_url(&c->base), NULL,
- html_convert_css_callback, c, &child, CONTENT_CSS,
- &c->stylesheets[STYLESHEET_USER].data.external);
- if (ns_error != NSERROR_OK)
- goto html_find_stylesheets_no_memory;
-
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- return true;
-
-html_find_stylesheets_no_memory:
- content_broadcast_errorcode(&c->base, ns_error);
- return false;
-}
-
-/**
- * Handle notification of inline style completion
- *
- * \param css Inline style object
- * \param pw Private data
- */
-static void html_inline_style_done(struct content_css_data *css, void *pw)
-{
- html_content *html = pw;
-
- html->base.active--;
- LOG(("%d fetches active", html->base.active));
-}
-
-static nserror
-html_stylesheet_from_domnode(html_content *c,
- dom_node *node,
- struct content_css_data **ret_sheet)
-{
- dom_node *child, *next;
- dom_exception exc;
- struct content_css_data *sheet;
- nserror error;
- css_error csserror;
-
- /* create stylesheet */
- sheet = calloc(1, sizeof(struct content_css_data));
- if (sheet == NULL) {
- return NSERROR_NOMEM;
- }
-
- error = nscss_create_css_data(sheet,
- nsurl_access(c->base_url), NULL, c->quirks,
- html_inline_style_done, c);
- if (error != NSERROR_OK) {
- free(sheet);
- return error;
- }
-
- exc = dom_node_get_first_child(node, &child);
- if (exc != DOM_NO_ERR) {
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_DOM;
- }
-
- while (child != NULL) {
- dom_string *data;
-
- exc = dom_node_get_text_content(child, &data);
- if (exc != DOM_NO_ERR) {
- dom_node_unref(child);
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_DOM;
- }
-
- if (nscss_process_css_data(sheet,
- dom_string_data(data),
- dom_string_byte_length(data)) == false) {
- dom_string_unref(data);
- dom_node_unref(child);
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_CSS;
- }
-
- dom_string_unref(data);
-
- exc = dom_node_get_next_sibling(child, &next);
- if (exc != DOM_NO_ERR) {
- dom_node_unref(child);
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_DOM;
- }
-
- dom_node_unref(child);
- child = next;
- }
-
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- /* Convert the content -- manually, as we want the result */
- csserror = nscss_convert_css_data(sheet);
- if (csserror != CSS_OK) {
- /* conversion failed */
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
- nscss_destroy_css_data(sheet);
- free(sheet);
- return css_error_to_nserror(csserror);
- }
-
- *ret_sheet = sheet;
- return NSERROR_OK;
-}
-
-/**
- * Process an inline stylesheet in the document.
- *
- * \param c content structure
- * \param style xml node of style element
- * \return true on success, false if an error occurred
- */
-
-static struct html_stylesheet *
-html_create_style_element(html_content *c, dom_node *style)
-{
- dom_string *val;
- dom_exception exc;
- struct html_stylesheet *stylesheets;
-
- /* ensure sheets are initialised */
- if (html_init_stylesheets(c) == false) {
- return false;
- }
-
- /* type='text/css', or not present (invalid but common) */
- exc = dom_element_get_attribute(style, corestring_dom_type, &val);
- if (exc == DOM_NO_ERR && val != NULL) {
- if (!dom_string_caseless_lwc_isequal(val,
- corestring_lwc_text_css)) {
- dom_string_unref(val);
- return NULL;
- }
- dom_string_unref(val);
- }
-
- /* media contains 'screen' or 'all' or not present */
- exc = dom_element_get_attribute(style, corestring_dom_media, &val);
- if (exc == DOM_NO_ERR && val != NULL) {
- if (strcasestr(dom_string_data(val), "screen") == NULL &&
- strcasestr(dom_string_data(val),
- "all") == NULL) {
- dom_string_unref(val);
- return NULL;
- }
- dom_string_unref(val);
- }
-
- /* Extend array */
- stylesheets = realloc(c->stylesheets,
- sizeof(struct html_stylesheet) * (c->stylesheet_count + 1));
- if (stylesheets == NULL) {
-
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
- return false;
-
- }
- c->stylesheets = stylesheets;
-
- c->stylesheets[c->stylesheet_count].type = HTML_STYLESHEET_INTERNAL;
- c->stylesheets[c->stylesheet_count].node = style;
- c->stylesheets[c->stylesheet_count].data.internal = NULL;
- c->stylesheet_count++;
-
- return c->stylesheets + (c->stylesheet_count - 1);
-}
-
-static bool html_process_style_element_update(html_content *c, dom_node *style)
-{
- struct content_css_data *sheet = NULL;
- nserror error;
- unsigned int i;
- struct html_stylesheet *s;
-
- /* Find sheet */
- for (i = 0, s = c->stylesheets; i != c->stylesheet_count; i++, s++) {
- if ((s->type == HTML_STYLESHEET_INTERNAL) &&
- (s->node == style))
- break;
- }
- if (i == c->stylesheet_count) {
- s = html_create_style_element(c, style);
- }
- if (s == NULL) {
- LOG(("Could not find or create inline stylesheet for %p",
- style));
- return false;
- }
-
- LOG(("Found sheet %p slot %d for node %p", s,i, style));
-
- error = html_stylesheet_from_domnode(c, style, &sheet);
- if (error != NSERROR_OK) {
- LOG(("Failed to update sheet"));
- content_broadcast_errorcode(&c->base, error);
- return false;
- }
-
- LOG(("Updating sheet %p with %p", s->data.internal, sheet));
-
- /* Update index */
- if (s->data.internal != NULL) {
- nscss_destroy_css_data(s->data.internal);
- free(s->data.internal);
- }
- s->data.internal = sheet;
- return true;
-}
-
-static bool html_process_stylesheet_link(html_content *htmlc, dom_node *node)
-{
- dom_string *rel, *type_attr, *media, *href;
- struct html_stylesheet *stylesheets;
- nsurl *joined;
- dom_exception exc;
- nserror ns_error;
- hlcache_child_context child;
-
- /* ensure sheets are initialised */
- if (html_init_stylesheets(htmlc) == false) {
- return false;
- }
-
- /* rel=<space separated list, including 'stylesheet'> */
- exc = dom_element_get_attribute(node, corestring_dom_rel, &rel);
- if (exc != DOM_NO_ERR || rel == NULL)
- return true;
-
- if (strcasestr(dom_string_data(rel), "stylesheet") == 0) {
- dom_string_unref(rel);
- return true;
- } else if (strcasestr(dom_string_data(rel), "alternate") != 0) {
- /* Ignore alternate stylesheets */
- dom_string_unref(rel);
- return true;
- }
- dom_string_unref(rel);
-
- /* type='text/css' or not present */
- exc = dom_element_get_attribute(node, corestring_dom_type, &type_attr);
- if (exc == DOM_NO_ERR && type_attr != NULL) {
- if (!dom_string_caseless_lwc_isequal(type_attr,
- corestring_lwc_text_css)) {
- dom_string_unref(type_attr);
- return true;
- }
- dom_string_unref(type_attr);
- }
-
- /* media contains 'screen' or 'all' or not present */
- exc = dom_element_get_attribute(node, corestring_dom_media, &media);
- if (exc == DOM_NO_ERR && media != NULL) {
- if (strcasestr(dom_string_data(media), "screen") == NULL &&
- strcasestr(dom_string_data(media), "all") == NULL) {
- dom_string_unref(media);
- return true;
- }
- dom_string_unref(media);
- }
-
- /* href='...' */
- exc = dom_element_get_attribute(node, corestring_dom_href, &href);
- if (exc != DOM_NO_ERR || href == NULL)
- return true;
-
- /* TODO: only the first preferred stylesheets (ie.
- * those with a title attribute) should be loaded
- * (see HTML4 14.3) */
-
- ns_error = nsurl_join(htmlc->base_url, dom_string_data(href), &joined);
- if (ns_error != NSERROR_OK) {
- dom_string_unref(href);
- goto no_memory;
- }
- dom_string_unref(href);
-
- LOG(("linked stylesheet %i '%s'", htmlc->stylesheet_count, nsurl_access(joined)));
-
- /* extend stylesheets array to allow for new sheet */
- stylesheets = realloc(htmlc->stylesheets,
- sizeof(struct html_stylesheet) * (htmlc->stylesheet_count + 1));
- if (stylesheets == NULL) {
- nsurl_unref(joined);
- ns_error = NSERROR_NOMEM;
- goto no_memory;
- }
-
- htmlc->stylesheets = stylesheets;
- htmlc->stylesheets[htmlc->stylesheet_count].type = HTML_STYLESHEET_EXTERNAL;
-
- /* start fetch */
- child.charset = htmlc->encoding;
- child.quirks = htmlc->base.quirks;
-
- ns_error = hlcache_handle_retrieve(joined,
- 0,
- content_get_url(&htmlc->base),
- NULL,
- html_convert_css_callback,
- htmlc,
- &child,
- CONTENT_CSS,
- &htmlc->stylesheets[htmlc->stylesheet_count].data.external);
-
- nsurl_unref(joined);
-
- if (ns_error != NSERROR_OK)
- goto no_memory;
-
- htmlc->stylesheet_count++;
-
- htmlc->base.active++;
- LOG(("%d fetches active", htmlc->base.active));
-
- return true;
-
-no_memory:
- content_broadcast_errorcode(&htmlc->base, ns_error);
- return false;
-}
-
/* callback for DOMNodeInserted end type */
static void
dom_default_action_DOMNodeInserted_cb(struct dom_event *evt, void *pw)
@@ -816,7 +245,7 @@ dom_default_action_DOMNodeInserted_cb(struct dom_event *evt, void *pw)
if ((exc == DOM_NO_ERR) && (name != NULL)) {
/* LOG(("element htmlc:%p node %p name:%s", htmlc, node, dom_string_data(name))); */
if (dom_string_caseless_isequal(name, corestring_dom_link)) {
- html_process_stylesheet_link(htmlc, (dom_node *)node);
+ html_css_process_link(htmlc, (dom_node *)node);
}
}
}
@@ -842,7 +271,7 @@ dom_default_action_DOMSubtreeModified_cb(struct dom_event *evt, void *pw)
if ((exc == DOM_NO_ERR) && (name != NULL)) {
/* LOG(("element htmlc:%p node:%p name:%s", htmlc, node, dom_string_data(name))); */
if (dom_string_caseless_isequal(name, corestring_dom_style)) {
- html_process_style_element_update(htmlc, (dom_node *)node);
+ html_css_update_style(htmlc, (dom_node *)node);
}
}
}
@@ -922,7 +351,7 @@ html_create_html_data(html_content *c, const http_parameter *params)
selection_prepare(&c->sel, (struct content *)c, true);
- nerror = http_parameter_list_find_item(params, html_charset, &charset);
+ nerror = http_parameter_list_find_item(params, corestring_lwc_charset, &charset);
if (nerror == NSERROR_OK) {
c->encoding = strdup(lwc_string_data(charset));
@@ -961,7 +390,6 @@ html_create_html_data(html_content *c, const http_parameter *params)
&c->parser,
&c->document);
}
-
if (error != DOM_HUBBUB_OK) {
nsurl_unref(c->base_url);
c->base_url = NULL;
@@ -1013,6 +441,13 @@ html_create(const content_handler *handler,
return error;
}
+ error = html_css_new_stylesheets(html);
+ if (error != NSERROR_OK) {
+ content_broadcast_errorcode(&html->base, error);
+ free(html);
+ return error;
+ }
+
*c = (struct content *) html;
return NSERROR_OK;
@@ -2243,11 +1678,6 @@ html_begin_conversion(html_content *htmlc)
dom_node_unref(head);
dom_node_unref(html);
- /* ensure stylesheets are initialised */
- if (html_init_stylesheets(htmlc) == false) {
- return false;
- }
-
if (htmlc->base.active == 0) {
html_finish_conversion(htmlc);
}
@@ -2522,7 +1952,6 @@ static void html_free_layout(html_content *htmlc)
static void html_destroy(struct content *c)
{
html_content *html = (html_content *) c;
- unsigned int i;
struct form *f, *g;
LOG(("content %p", c));
@@ -2582,19 +2011,7 @@ static void html_destroy(struct content *c)
}
/* Free stylesheets */
- for (i = 0; i != html->stylesheet_count; i++) {
- if (html->stylesheets[i].type == HTML_STYLESHEET_EXTERNAL &&
- html->stylesheets[i].data.external != NULL) {
- hlcache_handle_release(
- html->stylesheets[i].data.external);
- } else if (html->stylesheets[i].type ==
- HTML_STYLESHEET_INTERNAL &&
- html->stylesheets[i].data.internal != NULL) {
- nscss_destroy_css_data(
- html->stylesheets[i].data.internal);
- }
- }
- free(html->stylesheets);
+ html_css_free_stylesheets(html);
/* Free scripts */
html_free_scripts(html);
@@ -3291,25 +2708,6 @@ const char *html_get_base_target(hlcache_handle *h)
}
/**
- * Retrieve stylesheets used by HTML document
- *
- * \param h Content to retrieve stylesheets from
- * \param n Pointer to location to receive number of sheets
- * \return Pointer to array of stylesheets
- */
-struct html_stylesheet *html_get_stylesheets(hlcache_handle *h, unsigned int *n)
-{
- html_content *c = (html_content *) hlcache_handle_get_content(h);
-
- assert(c != NULL);
- assert(n != NULL);
-
- *n = c->stylesheet_count;
-
- return c->stylesheets;
-}
-
-/**
* Retrieve objects used by HTML document
*
* \param h Content to retrieve objects from
@@ -3369,30 +2767,7 @@ static void html_fini(void)
{
box_construct_fini();
- if (html_user_stylesheet_url != NULL) {
- nsurl_unref(html_user_stylesheet_url);
- html_user_stylesheet_url = NULL;
- }
-
- if (html_quirks_stylesheet_url != NULL) {
- nsurl_unref(html_quirks_stylesheet_url);
- html_quirks_stylesheet_url = NULL;
- }
-
- if (html_adblock_stylesheet_url != NULL) {
- nsurl_unref(html_adblock_stylesheet_url);
- html_adblock_stylesheet_url = NULL;
- }
-
- if (html_default_stylesheet_url != NULL) {
- nsurl_unref(html_default_stylesheet_url);
- html_default_stylesheet_url = NULL;
- }
-
- if (html_charset != NULL) {
- lwc_string_unref(html_charset);
- html_charset = NULL;
- }
+ html_css_fini();
}
static const content_handler html_content_handler = {
@@ -3423,32 +2798,9 @@ static const content_handler html_content_handler = {
nserror html_init(void)
{
uint32_t i;
- lwc_error lerror;
nserror error;
- lerror = lwc_intern_string("charset", SLEN("charset"), &html_charset);
- if (lerror != lwc_error_ok) {
- error = NSERROR_NOMEM;
- goto error;
- }
-
- error = nsurl_create("resource:default.css",
- &html_default_stylesheet_url);
- if (error != NSERROR_OK)
- goto error;
-
- error = nsurl_create("resource:adblock.css",
- &html_adblock_stylesheet_url);
- if (error != NSERROR_OK)
- goto error;
-
- error = nsurl_create("resource:quirks.css",
- &html_quirks_stylesheet_url);
- if (error != NSERROR_OK)
- goto error;
-
- error = nsurl_create("resource:user.css",
- &html_user_stylesheet_url);
+ error = html_css_init();
if (error != NSERROR_OK)
goto error;
diff --git a/render/html.h b/render/html.h
index 6920fa8c7..97899f136 100644
--- a/render/html.h
+++ b/render/html.h
@@ -182,8 +182,17 @@ struct content_html_frames *html_get_frameset(struct hlcache_handle *h);
struct content_html_iframe *html_get_iframe(struct hlcache_handle *h);
nsurl *html_get_base_url(struct hlcache_handle *h);
const char *html_get_base_target(struct hlcache_handle *h);
+
+/**
+ * Retrieve stylesheets used by HTML document
+ *
+ * \param h Content to retrieve stylesheets from
+ * \param n Pointer to location to receive number of sheets
+ * \return Pointer to array of stylesheets
+ */
struct html_stylesheet *html_get_stylesheets(struct hlcache_handle *h,
unsigned int *n);
+
struct content_html_object *html_get_objects(struct hlcache_handle *h,
unsigned int *n);
bool html_get_id_offset(struct hlcache_handle *h, lwc_string *frag_id,
diff --git a/render/html_css.c b/render/html_css.c
new file mode 100644
index 000000000..babe052ce
--- /dev/null
+++ b/render/html_css.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright 2013 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf 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; version 2 of the License.
+ *
+ * NetSurf 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Processing for html content css operations.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+
+#include "content/hlcache.h"
+#include "desktop/options.h"
+#include "render/html_internal.h"
+#include "utils/corestrings.h"
+#include "utils/config.h"
+#include "utils/log.h"
+
+static nsurl *html_default_stylesheet_url;
+static nsurl *html_adblock_stylesheet_url;
+static nsurl *html_quirks_stylesheet_url;
+static nsurl *html_user_stylesheet_url;
+
+static nserror css_error_to_nserror(css_error error)
+{
+ switch (error) {
+ case CSS_OK:
+ return NSERROR_OK;
+
+ case CSS_NOMEM:
+ return NSERROR_NOMEM;
+
+ case CSS_BADPARM:
+ return NSERROR_BAD_PARAMETER;
+
+ case CSS_INVALID:
+ return NSERROR_INVALID;
+
+ case CSS_FILENOTFOUND:
+ return NSERROR_NOT_FOUND;
+
+ case CSS_NEEDDATA:
+ return NSERROR_NEED_DATA;
+
+ case CSS_BADCHARSET:
+ return NSERROR_BAD_ENCODING;
+
+ case CSS_EOF:
+ case CSS_IMPORTS_PENDING:
+ case CSS_PROPERTY_NOT_SET:
+ default:
+ break;
+ }
+ return NSERROR_CSS;
+}
+
+/**
+ * Callback for fetchcache() for linked stylesheets.
+ */
+
+static nserror
+html_convert_css_callback(hlcache_handle *css,
+ const hlcache_event *event,
+ void *pw)
+{
+ html_content *parent = pw;
+ unsigned int i;
+ struct html_stylesheet *s;
+
+ /* Find sheet */
+ for (i = 0, s = parent->stylesheets;
+ i != parent->stylesheet_count;
+ i++, s++) {
+ if (s->type == HTML_STYLESHEET_EXTERNAL &&
+ s->data.external == css)
+ break;
+ }
+
+ assert(i != parent->stylesheet_count);
+
+ switch (event->type) {
+ case CONTENT_MSG_LOADING:
+ break;
+
+ case CONTENT_MSG_READY:
+ break;
+
+ case CONTENT_MSG_DONE:
+ LOG(("done stylesheet slot %d '%s'", i,
+ nsurl_access(hlcache_handle_get_url(css))));
+ parent->base.active--;
+ LOG(("%d fetches active", parent->base.active));
+ break;
+
+ case CONTENT_MSG_ERROR:
+ LOG(("stylesheet %s failed: %s",
+ nsurl_access(hlcache_handle_get_url(css)),
+ event->data.error));
+ hlcache_handle_release(css);
+ s->data.external = NULL;
+ parent->base.active--;
+ LOG(("%d fetches active", parent->base.active));
+ content_add_error(&parent->base, "?", 0);
+ break;
+
+ case CONTENT_MSG_STATUS:
+ if (event->data.explicit_status_text == NULL) {
+ /* Object content's status text updated */
+ html_set_status(parent,
+ content_get_status_message(css));
+ content_broadcast(&parent->base, CONTENT_MSG_STATUS,
+ event->data);
+ } else {
+ /* Object content wants to set explicit message */
+ content_broadcast(&parent->base, CONTENT_MSG_STATUS,
+ event->data);
+ }
+ break;
+
+ case CONTENT_MSG_POINTER:
+ /* Really don't want this to continue after the switch */
+ return NSERROR_OK;
+
+ default:
+ assert(0);
+ }
+
+ if (parent->base.active == 0) {
+ html_begin_conversion(parent);
+ }
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in render/html.h */
+struct html_stylesheet *html_get_stylesheets(hlcache_handle *h, unsigned int *n)
+{
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
+
+ assert(c != NULL);
+ assert(n != NULL);
+
+ *n = c->stylesheet_count;
+
+ return c->stylesheets;
+}
+
+
+/* exported interface documented in render/html_internal.h */
+nserror html_css_free_stylesheets(html_content *html)
+{
+ unsigned int i;
+
+ for (i = 0; i != html->stylesheet_count; i++) {
+ if ((html->stylesheets[i].type == HTML_STYLESHEET_EXTERNAL) &&
+ (html->stylesheets[i].data.external != NULL)) {
+ hlcache_handle_release(html->stylesheets[i].data.external);
+ } else if ((html->stylesheets[i].type == HTML_STYLESHEET_INTERNAL) &&
+ (html->stylesheets[i].data.internal != NULL)) {
+ nscss_destroy_css_data(html->stylesheets[i].data.internal);
+ }
+ }
+ free(html->stylesheets);
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in render/html_internal.h */
+nserror html_css_new_stylesheets(html_content *c)
+{
+ nserror ns_error;
+ hlcache_child_context child;
+
+ if (c->stylesheets != NULL) {
+ return NSERROR_OK; /* already initialised */
+ }
+
+ /* stylesheet 0 is the base style sheet,
+ * stylesheet 1 is the quirks mode style sheet,
+ * stylesheet 2 is the adblocking stylesheet,
+ * stylesheet 3 is the user stylesheet */
+ c->stylesheets = calloc(STYLESHEET_START, sizeof(struct html_stylesheet));
+ if (c->stylesheets == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ c->stylesheets[STYLESHEET_BASE].type = HTML_STYLESHEET_EXTERNAL;
+ c->stylesheets[STYLESHEET_BASE].data.external = NULL;
+ c->stylesheets[STYLESHEET_QUIRKS].type = HTML_STYLESHEET_EXTERNAL;
+ c->stylesheets[STYLESHEET_QUIRKS].data.external = NULL;
+ c->stylesheets[STYLESHEET_ADBLOCK].type = HTML_STYLESHEET_EXTERNAL;
+ c->stylesheets[STYLESHEET_ADBLOCK].data.external = NULL;
+ c->stylesheets[STYLESHEET_USER].type = HTML_STYLESHEET_EXTERNAL;
+ c->stylesheets[STYLESHEET_USER].data.external = NULL;
+ c->stylesheet_count = STYLESHEET_START;
+
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ ns_error = hlcache_handle_retrieve(html_default_stylesheet_url, 0,
+ content_get_url(&c->base), NULL,
+ html_convert_css_callback, c, &child, CONTENT_CSS,
+ &c->stylesheets[STYLESHEET_BASE].data.external);
+ if (ns_error != NSERROR_OK) {
+ return ns_error;
+ }
+
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+
+ if (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL) {
+ ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url,
+ 0, content_get_url(&c->base), NULL,
+ html_convert_css_callback, c, &child,
+ CONTENT_CSS,
+ &c->stylesheets[STYLESHEET_QUIRKS].data.external);
+ if (ns_error != NSERROR_OK) {
+ return ns_error;
+ }
+
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+
+ }
+
+ if (nsoption_bool(block_ads)) {
+ ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url,
+ 0, content_get_url(&c->base), NULL,
+ html_convert_css_callback, c, &child, CONTENT_CSS,
+ &c->stylesheets[STYLESHEET_ADBLOCK].
+ data.external);
+ if (ns_error != NSERROR_OK) {
+ return ns_error;
+ }
+
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+
+ }
+
+ ns_error = hlcache_handle_retrieve(html_user_stylesheet_url, 0,
+ content_get_url(&c->base), NULL,
+ html_convert_css_callback, c, &child, CONTENT_CSS,
+ &c->stylesheets[STYLESHEET_USER].data.external);
+ if (ns_error != NSERROR_OK) {
+ return ns_error;
+ }
+
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+
+ return ns_error;
+}
+
+/**
+ * Handle notification of inline style completion
+ *
+ * \param css Inline style object
+ * \param pw Private data
+ */
+static void html_inline_style_done(struct content_css_data *css, void *pw)
+{
+ html_content *html = pw;
+
+ html->base.active--;
+ LOG(("%d fetches active", html->base.active));
+}
+
+static nserror
+html_stylesheet_from_domnode(html_content *c,
+ dom_node *node,
+ struct content_css_data **ret_sheet)
+{
+ dom_node *child, *next;
+ dom_exception exc;
+ struct content_css_data *sheet;
+ nserror error;
+ css_error csserror;
+
+ /* create stylesheet */
+ sheet = calloc(1, sizeof(struct content_css_data));
+ if (sheet == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ error = nscss_create_css_data(sheet,
+ nsurl_access(c->base_url), NULL, c->quirks,
+ html_inline_style_done, c);
+ if (error != NSERROR_OK) {
+ free(sheet);
+ return error;
+ }
+
+ exc = dom_node_get_first_child(node, &child);
+ if (exc != DOM_NO_ERR) {
+ nscss_destroy_css_data(sheet);
+ free(sheet);
+ return NSERROR_DOM;
+ }
+
+ while (child != NULL) {
+ dom_string *data;
+
+ exc = dom_node_get_text_content(child, &data);
+ if (exc != DOM_NO_ERR) {
+ dom_node_unref(child);
+ nscss_destroy_css_data(sheet);
+ free(sheet);
+ return NSERROR_DOM;
+ }
+
+ if (nscss_process_css_data(sheet,
+ dom_string_data(data),
+ dom_string_byte_length(data)) == false) {
+ dom_string_unref(data);
+ dom_node_unref(child);
+ nscss_destroy_css_data(sheet);
+ free(sheet);
+ return NSERROR_CSS;
+ }
+
+ dom_string_unref(data);
+
+ exc = dom_node_get_next_sibling(child, &next);
+ if (exc != DOM_NO_ERR) {
+ dom_node_unref(child);
+ nscss_destroy_css_data(sheet);
+ free(sheet);
+ return NSERROR_DOM;
+ }
+
+ dom_node_unref(child);
+ child = next;
+ }
+
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+
+ /* Convert the content -- manually, as we want the result */
+ csserror = nscss_convert_css_data(sheet);
+ if (csserror != CSS_OK) {
+ /* conversion failed */
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
+ nscss_destroy_css_data(sheet);
+ free(sheet);
+ return css_error_to_nserror(csserror);
+ }
+
+ *ret_sheet = sheet;
+ return NSERROR_OK;
+}
+
+/**
+ * Process an inline stylesheet in the document.
+ *
+ * \param c content structure
+ * \param style xml node of style element
+ * \return true on success, false if an error occurred
+ */
+
+static struct html_stylesheet *
+html_create_style_element(html_content *c, dom_node *style)
+{
+ dom_string *val;
+ dom_exception exc;
+ struct html_stylesheet *stylesheets;
+
+ /* type='text/css', or not present (invalid but common) */
+ exc = dom_element_get_attribute(style, corestring_dom_type, &val);
+ if (exc == DOM_NO_ERR && val != NULL) {
+ if (!dom_string_caseless_lwc_isequal(val,
+ corestring_lwc_text_css)) {
+ dom_string_unref(val);
+ return NULL;
+ }
+ dom_string_unref(val);
+ }
+
+ /* media contains 'screen' or 'all' or not present */
+ exc = dom_element_get_attribute(style, corestring_dom_media, &val);
+ if (exc == DOM_NO_ERR && val != NULL) {
+ if (strcasestr(dom_string_data(val), "screen") == NULL &&
+ strcasestr(dom_string_data(val),
+ "all") == NULL) {
+ dom_string_unref(val);
+ return NULL;
+ }
+ dom_string_unref(val);
+ }
+
+ /* Extend array */
+ stylesheets = realloc(c->stylesheets,
+ sizeof(struct html_stylesheet) * (c->stylesheet_count + 1));
+ if (stylesheets == NULL) {
+
+ content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
+ return false;
+
+ }
+ c->stylesheets = stylesheets;
+
+ c->stylesheets[c->stylesheet_count].type = HTML_STYLESHEET_INTERNAL;
+ c->stylesheets[c->stylesheet_count].node = style;
+ c->stylesheets[c->stylesheet_count].data.internal = NULL;
+ c->stylesheet_count++;
+
+ return c->stylesheets + (c->stylesheet_count - 1);
+}
+
+bool html_css_update_style(html_content *c, dom_node *style)
+{
+ struct content_css_data *sheet = NULL;
+ nserror error;
+ unsigned int i;
+ struct html_stylesheet *s;
+
+ /* Find sheet */
+ for (i = 0, s = c->stylesheets; i != c->stylesheet_count; i++, s++) {
+ if ((s->type == HTML_STYLESHEET_INTERNAL) &&
+ (s->node == style))
+ break;
+ }
+ if (i == c->stylesheet_count) {
+ s = html_create_style_element(c, style);
+ }
+ if (s == NULL) {
+ LOG(("Could not find or create inline stylesheet for %p",
+ style));
+ return false;
+ }
+
+ LOG(("Found sheet %p slot %d for node %p", s,i, style));
+
+ error = html_stylesheet_from_domnode(c, style, &sheet);
+ if (error != NSERROR_OK) {
+ LOG(("Failed to update sheet"));
+ content_broadcast_errorcode(&c->base, error);
+ return false;
+ }
+
+ LOG(("Updating sheet %p with %p", s->data.internal, sheet));
+
+ /* Update index */
+ if (s->data.internal != NULL) {
+ nscss_destroy_css_data(s->data.internal);
+ free(s->data.internal);
+ }
+ s->data.internal = sheet;
+ return true;
+}
+
+bool html_css_process_link(html_content *htmlc, dom_node *node)
+{
+ dom_string *rel, *type_attr, *media, *href;
+ struct html_stylesheet *stylesheets;
+ nsurl *joined;
+ dom_exception exc;
+ nserror ns_error;
+ hlcache_child_context child;
+
+ /* rel=<space separated list, including 'stylesheet'> */
+ exc = dom_element_get_attribute(node, corestring_dom_rel, &rel);
+ if (exc != DOM_NO_ERR || rel == NULL)
+ return true;
+
+ if (strcasestr(dom_string_data(rel), "stylesheet") == 0) {
+ dom_string_unref(rel);
+ return true;
+ } else if (strcasestr(dom_string_data(rel), "alternate") != 0) {
+ /* Ignore alternate stylesheets */
+ dom_string_unref(rel);
+ return true;
+ }
+ dom_string_unref(rel);
+
+ /* type='text/css' or not present */
+ exc = dom_element_get_attribute(node, corestring_dom_type, &type_attr);
+ if (exc == DOM_NO_ERR && type_attr != NULL) {
+ if (!dom_string_caseless_lwc_isequal(type_attr,
+ corestring_lwc_text_css)) {
+ dom_string_unref(type_attr);
+ return true;
+ }
+ dom_string_unref(type_attr);
+ }
+
+ /* media contains 'screen' or 'all' or not present */
+ exc = dom_element_get_attribute(node, corestring_dom_media, &media);
+ if (exc == DOM_NO_ERR && media != NULL) {
+ if (strcasestr(dom_string_data(media), "screen") == NULL &&
+ strcasestr(dom_string_data(media), "all") == NULL) {
+ dom_string_unref(media);
+ return true;
+ }
+ dom_string_unref(media);
+ }
+
+ /* href='...' */
+ exc = dom_element_get_attribute(node, corestring_dom_href, &href);
+ if (exc != DOM_NO_ERR || href == NULL)
+ return true;
+
+ /* TODO: only the first preferred stylesheets (ie.
+ * those with a title attribute) should be loaded
+ * (see HTML4 14.3) */
+
+ ns_error = nsurl_join(htmlc->base_url, dom_string_data(href), &joined);
+ if (ns_error != NSERROR_OK) {
+ dom_string_unref(href);
+ goto no_memory;
+ }
+ dom_string_unref(href);
+
+ LOG(("linked stylesheet %i '%s'", htmlc->stylesheet_count, nsurl_access(joined)));
+
+ /* extend stylesheets array to allow for new sheet */
+ stylesheets = realloc(htmlc->stylesheets,
+ sizeof(struct html_stylesheet) * (htmlc->stylesheet_count + 1));
+ if (stylesheets == NULL) {
+ nsurl_unref(joined);
+ ns_error = NSERROR_NOMEM;
+ goto no_memory;
+ }
+
+ htmlc->stylesheets = stylesheets;
+ htmlc->stylesheets[htmlc->stylesheet_count].type = HTML_STYLESHEET_EXTERNAL;
+
+ /* start fetch */
+ child.charset = htmlc->encoding;
+ child.quirks = htmlc->base.quirks;
+
+ ns_error = hlcache_handle_retrieve(joined,
+ 0,
+ content_get_url(&htmlc->base),
+ NULL,
+ html_convert_css_callback,
+ htmlc,
+ &child,
+ CONTENT_CSS,
+ &htmlc->stylesheets[htmlc->stylesheet_count].data.external);
+
+ nsurl_unref(joined);
+
+ if (ns_error != NSERROR_OK)
+ goto no_memory;
+
+ htmlc->stylesheet_count++;
+
+ htmlc->base.active++;
+ LOG(("%d fetches active", htmlc->base.active));
+
+ return true;
+
+no_memory:
+ content_broadcast_errorcode(&htmlc->base, ns_error);
+ return false;
+}
+
+nserror
+html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
+{
+ uint32_t i;
+ css_error css_ret;
+ css_select_ctx *select_ctx;
+
+ /* check that the base stylesheet loaded; layout fails without it */
+ if (c->stylesheets[STYLESHEET_BASE].data.external == NULL) {
+ return NSERROR_CSS_BASE;
+ }
+
+ /* Create selection context */
+ css_ret = css_select_ctx_create(ns_realloc, c, &select_ctx);
+ if (css_ret != CSS_OK) {
+ return css_error_to_nserror(css_ret);
+ }
+
+ /* Add sheets to it */
+ for (i = STYLESHEET_BASE; i != c->stylesheet_count; i++) {
+ const struct html_stylesheet *hsheet = &c->stylesheets[i];
+ css_stylesheet *sheet = NULL;
+ css_origin origin = CSS_ORIGIN_AUTHOR;
+
+ if (i < STYLESHEET_USER) {
+ origin = CSS_ORIGIN_UA;
+ } else if (i < STYLESHEET_START) {
+ origin = CSS_ORIGIN_USER;
+ }
+
+ if ((hsheet->type == HTML_STYLESHEET_EXTERNAL) &&
+ (hsheet->data.external != NULL)) {
+ sheet = nscss_get_stylesheet(hsheet->data.external);
+ } else if (hsheet->type == HTML_STYLESHEET_INTERNAL) {
+ sheet = hsheet->data.internal->sheet;
+ }
+
+ if (sheet != NULL) {
+ css_ret = css_select_ctx_append_sheet(select_ctx,
+ sheet,
+ origin,
+ CSS_MEDIA_SCREEN);
+ if (css_ret != CSS_OK) {
+ css_select_ctx_destroy(select_ctx);
+ return css_error_to_nserror(css_ret);
+ }
+ }
+ }
+
+ /* return new selection context to caller */
+ *ret_select_ctx = select_ctx;
+ return NSERROR_OK;
+}
+
+nserror html_css_init(void)
+{
+ nserror error;
+
+ error = nsurl_create("resource:default.css",
+ &html_default_stylesheet_url);
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nsurl_create("resource:adblock.css",
+ &html_adblock_stylesheet_url);
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nsurl_create("resource:quirks.css",
+ &html_quirks_stylesheet_url);
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nsurl_create("resource:user.css",
+ &html_user_stylesheet_url);
+
+ return error;
+}
+
+void html_css_fini(void)
+{
+ if (html_user_stylesheet_url != NULL) {
+ nsurl_unref(html_user_stylesheet_url);
+ html_user_stylesheet_url = NULL;
+ }
+
+ if (html_quirks_stylesheet_url != NULL) {
+ nsurl_unref(html_quirks_stylesheet_url);
+ html_quirks_stylesheet_url = NULL;
+ }
+
+ if (html_adblock_stylesheet_url != NULL) {
+ nsurl_unref(html_adblock_stylesheet_url);
+ html_adblock_stylesheet_url = NULL;
+ }
+
+ if (html_default_stylesheet_url != NULL) {
+ nsurl_unref(html_default_stylesheet_url);
+ html_default_stylesheet_url = NULL;
+ }
+}
diff --git a/render/html_internal.h b/render/html_internal.h
index 80b126b25..2dd1c5190 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -255,6 +255,24 @@ struct form *html_forms_get_forms(const char *docenc, dom_html_document *doc);
struct form_control *html_forms_get_control_for_node(struct form *forms,
dom_node *node);
+/* in render/html_css.c */
+nserror html_css_init(void);
+void html_css_fini(void);
+
+/**
+ * Initialise core stylesheets for a content
+ *
+ * \param c content structure to update
+ * \return nserror
+ */
+nserror html_css_new_stylesheets(html_content *c);
+nserror html_css_free_stylesheets(html_content *html);
+
+bool html_css_process_link(html_content *htmlc, dom_node *node);
+bool html_css_update_style(html_content *c, dom_node *style);
+
+nserror html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx);
+
/* Useful dom_string pointers */
struct dom_string;
diff --git a/utils/corestrings.c b/utils/corestrings.c
index 06c7906bd..cc1d6154a 100644
--- a/utils/corestrings.c
+++ b/utils/corestrings.c
@@ -38,6 +38,7 @@ lwc_string *corestring_lwc_bottom;
lwc_string *corestring_lwc_button;
lwc_string *corestring_lwc_caption;
lwc_string *corestring_lwc_center;
+lwc_string *corestring_lwc_charset;
lwc_string *corestring_lwc_checkbox;
lwc_string *corestring_lwc_circle;
lwc_string *corestring_lwc_col;
@@ -257,6 +258,7 @@ void corestrings_fini(void)
CSS_LWC_STRING_UNREF(bottom);
CSS_LWC_STRING_UNREF(button);
CSS_LWC_STRING_UNREF(caption);
+ CSS_LWC_STRING_UNREF(charset);
CSS_LWC_STRING_UNREF(center);
CSS_LWC_STRING_UNREF(checkbox);
CSS_LWC_STRING_UNREF(circle);
@@ -497,6 +499,7 @@ nserror corestrings_init(void)
CSS_LWC_STRING_INTERN(bottom);
CSS_LWC_STRING_INTERN(button);
CSS_LWC_STRING_INTERN(caption);
+ CSS_LWC_STRING_INTERN(charset);
CSS_LWC_STRING_INTERN(center);
CSS_LWC_STRING_INTERN(checkbox);
CSS_LWC_STRING_INTERN(circle);
diff --git a/utils/corestrings.h b/utils/corestrings.h
index d4e8fc3f7..8cfd23977 100644
--- a/utils/corestrings.h
+++ b/utils/corestrings.h
@@ -42,6 +42,7 @@ extern lwc_string *corestring_lwc_bottom;
extern lwc_string *corestring_lwc_button;
extern lwc_string *corestring_lwc_caption;
extern lwc_string *corestring_lwc_center;
+extern lwc_string *corestring_lwc_charset;
extern lwc_string *corestring_lwc_checkbox;
extern lwc_string *corestring_lwc_circle;
extern lwc_string *corestring_lwc_col;