diff options
author | Vincent Sanders <vince@netsurf-browser.org> | 2018-05-10 11:34:26 +0100 |
---|---|---|
committer | Vincent Sanders <vince@kyllikki.org> | 2018-05-10 13:37:02 +0100 |
commit | 2a03ea30490892ac52b3da325ab78e1aa888f83e (patch) | |
tree | d041e4a2aab3b224ad41612d47ea2119895e27ac /render/html_css.c | |
parent | 1b892391d7859398c212b9fda5b532308fa6e8fd (diff) | |
download | netsurf-2a03ea30490892ac52b3da325ab78e1aa888f83e.tar.gz netsurf-2a03ea30490892ac52b3da325ab78e1aa888f83e.tar.bz2 |
move html and text content handlers where they belong
Diffstat (limited to 'render/html_css.c')
-rw-r--r-- | render/html_css.c | 713 |
1 files changed, 0 insertions, 713 deletions
diff --git a/render/html_css.c b/render/html_css.c deleted file mode 100644 index 45bc16f56..000000000 --- a/render/html_css.c +++ /dev/null @@ -1,713 +0,0 @@ -/* - * 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 "utils/nsoption.h" -#include "utils/corestrings.h" -#include "utils/config.h" -#include "utils/log.h" -#include "netsurf/misc.h" -#include "netsurf/content.h" -#include "content/hlcache.h" -#include "css/css.h" -#include "desktop/gui_internal.h" - -#include "render/html_internal.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 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->sheet == css) - break; - } - - assert(i != parent->stylesheet_count); - - switch (event->type) { - - case CONTENT_MSG_DONE: - NSLOG(netsurf, INFO, "done stylesheet slot %d '%s'", i, - nsurl_access(hlcache_handle_get_url(css))); - parent->base.active--; - NSLOG(netsurf, INFO, "%d fetches active", parent->base.active); - break; - - case CONTENT_MSG_ERROR: - NSLOG(netsurf, INFO, "stylesheet %s failed: %s", - nsurl_access(hlcache_handle_get_url(css)), - event->data.error); - /* fall through */ - - case CONTENT_MSG_ERRORCODE: - hlcache_handle_release(css); - s->sheet = NULL; - parent->base.active--; - NSLOG(netsurf, INFO, "%d fetches active", parent->base.active); - content_add_error(&parent->base, "?", 0); - break; - - case CONTENT_MSG_POINTER: - /* Really don't want this to continue after the switch */ - return NSERROR_OK; - - default: - break; - } - - if (html_can_begin_conversion(parent)) { - html_begin_conversion(parent); - } - - return NSERROR_OK; -} - -static nserror -html_stylesheet_from_domnode(html_content *c, - dom_node *node, - hlcache_handle **sheet) -{ - hlcache_child_context child; - dom_string *style; - nsurl *url; - dom_exception exc; - nserror error; - uint32_t key; - char urlbuf[64]; - - child.charset = c->encoding; - child.quirks = c->base.quirks; - - exc = dom_node_get_text_content(node, &style); - if ((exc != DOM_NO_ERR) || (style == NULL)) { - NSLOG(netsurf, INFO, "No text content"); - return NSERROR_OK; - } - - error = html_css_fetcher_add_item(style, c->base_url, &key); - if (error != NSERROR_OK) { - dom_string_unref(style); - return error; - } - - dom_string_unref(style); - - snprintf(urlbuf, sizeof(urlbuf), "x-ns-css:%u", key); - - error = nsurl_create(urlbuf, &url); - if (error != NSERROR_OK) { - return error; - } - - error = hlcache_handle_retrieve(url, 0, - content_get_url(&c->base), NULL, - html_convert_css_callback, c, &child, CONTENT_CSS, - sheet); - if (error != NSERROR_OK) { - nsurl_unref(url); - return error; - } - - nsurl_unref(url); - - c->base.active++; - NSLOG(netsurf, INFO, "%d fetches active", c->base.active); - - 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].node = dom_node_ref(style); - c->stylesheets[c->stylesheet_count].sheet = NULL; - c->stylesheets[c->stylesheet_count].modified = false; - c->stylesheets[c->stylesheet_count].unused = false; - c->stylesheet_count++; - - return c->stylesheets + (c->stylesheet_count - 1); -} - -static bool html_css_process_modified_style(html_content *c, - struct html_stylesheet *s) -{ - hlcache_handle *sheet = NULL; - nserror error; - - error = html_stylesheet_from_domnode(c, s->node, &sheet); - if (error != NSERROR_OK) { - NSLOG(netsurf, INFO, "Failed to update sheet"); - content_broadcast_errorcode(&c->base, error); - return false; - } - - if (sheet != NULL) { - NSLOG(netsurf, INFO, "Updating sheet %p with %p", s->sheet, - sheet); - - if (s->sheet != NULL) { - switch (content_get_status(s->sheet)) { - case CONTENT_STATUS_DONE: - break; - default: - hlcache_handle_abort(s->sheet); - c->base.active--; - NSLOG(netsurf, INFO, "%d fetches active", - c->base.active); - } - hlcache_handle_release(s->sheet); - } - s->sheet = sheet; - } - - s->modified = false; - - return true; -} - -static void html_css_process_modified_styles(void *pw) -{ - html_content *c = pw; - struct html_stylesheet *s; - unsigned int i; - bool all_done = true; - - for (i = 0, s = c->stylesheets; i != c->stylesheet_count; i++, s++) { - if (c->stylesheets[i].modified) { - all_done &= html_css_process_modified_style(c, s); - } - } - - /* If we failed to process any sheet, schedule a retry */ - if (all_done == false) { - guit->misc->schedule(1000, html_css_process_modified_styles, c); - } -} - -bool html_css_update_style(html_content *c, dom_node *style) -{ - unsigned int i; - struct html_stylesheet *s; - - /* Find sheet */ - for (i = 0, s = c->stylesheets; i != c->stylesheet_count; i++, s++) { - if (s->node == style) - break; - } - if (i == c->stylesheet_count) { - s = html_create_style_element(c, style); - } - if (s == NULL) { - NSLOG(netsurf, INFO, - "Could not find or create inline stylesheet for %p", - style); - return false; - } - - s->modified = true; - - guit->misc->schedule(0, html_css_process_modified_styles, c); - - return true; -} - -bool html_css_process_style(html_content *c, dom_node *node) -{ - unsigned int i; - dom_string *val; - dom_exception exc; - struct html_stylesheet *s; - - /* Find sheet */ - for (i = 0, s = c->stylesheets; i != c->stylesheet_count; i++, s++) { - if (s->node == node) - break; - } - - /* Should already exist */ - if (i == c->stylesheet_count) { - return false; - } - - exc = dom_element_get_attribute(node, 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) { - s->unused = true; - } - dom_string_unref(val); - } - - 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); - - NSLOG(netsurf, INFO, "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].node = NULL; - htmlc->stylesheets[htmlc->stylesheet_count].modified = false; - htmlc->stylesheets[htmlc->stylesheet_count].unused = false; - - /* 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].sheet); - - nsurl_unref(joined); - - if (ns_error != NSERROR_OK) - goto no_memory; - - htmlc->stylesheet_count++; - - htmlc->base.active++; - NSLOG(netsurf, INFO, "%d fetches active", htmlc->base.active); - - return true; - -no_memory: - content_broadcast_errorcode(&htmlc->base, ns_error); - return false; -} - -/* 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; - - guit->misc->schedule(-1, html_css_process_modified_styles, html); - - for (i = 0; i != html->stylesheet_count; i++) { - if (html->stylesheets[i].sheet != NULL) { - hlcache_handle_release(html->stylesheets[i].sheet); - } - if (html->stylesheets[i].node != NULL) { - dom_node_unref(html->stylesheets[i].node); - } - } - free(html->stylesheets); - - return NSERROR_OK; -} - -/* exported interface documented in render/html_internal.h */ -nserror html_css_quirks_stylesheets(html_content *c) -{ - nserror ns_error = NSERROR_OK; - hlcache_child_context child; - - assert(c->stylesheets != NULL); - - if (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL) { - child.charset = c->encoding; - child.quirks = c->base.quirks; - - 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].sheet); - if (ns_error != NSERROR_OK) { - return ns_error; - } - - c->base.active++; - NSLOG(netsurf, INFO, "%d fetches active", c->base.active); - } - - return ns_error; -} - -/* 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].sheet = NULL; - c->stylesheets[STYLESHEET_QUIRKS].sheet = NULL; - c->stylesheets[STYLESHEET_ADBLOCK].sheet = NULL; - c->stylesheets[STYLESHEET_USER].sheet = 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].sheet); - if (ns_error != NSERROR_OK) { - return ns_error; - } - - c->base.active++; - NSLOG(netsurf, INFO, "%d fetches active", c->base.active); - - - if (nsoption_bool(block_advertisements)) { - 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].sheet); - if (ns_error != NSERROR_OK) { - return ns_error; - } - - c->base.active++; - NSLOG(netsurf, INFO, "%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].sheet); - if (ns_error != NSERROR_OK) { - return ns_error; - } - - c->base.active++; - NSLOG(netsurf, INFO, "%d fetches active", c->base.active); - - return ns_error; -} - -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].sheet == NULL) { - return NSERROR_CSS_BASE; - } - - /* Create selection context */ - css_ret = css_select_ctx_create(&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; - - /* Filter out stylesheets for non-screen media. */ - if (hsheet->unused) { - continue; - } - - if (i < STYLESHEET_USER) { - origin = CSS_ORIGIN_UA; - } else if (i < STYLESHEET_START) { - origin = CSS_ORIGIN_USER; - } - - if (hsheet->sheet != NULL) { - sheet = nscss_get_stylesheet(hsheet->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 = html_css_fetcher_register(); - if (error != NSERROR_OK) - return 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; - } -} |