diff options
Diffstat (limited to 'css')
-rw-r--r-- | css/css.c | 214 | ||||
-rw-r--r-- | css/css.h | 14 | ||||
-rw-r--r-- | css/select.c | 46 | ||||
-rw-r--r-- | css/select.h | 14 |
4 files changed, 210 insertions, 78 deletions
@@ -31,11 +31,22 @@ #include "utils/http.h" #include "utils/log.h" #include "utils/messages.h" +#include "utils/talloc.h" /* Define to trace import fetches */ #undef NSCSS_IMPORT_TRACE /** + * CSS content data + */ +typedef struct nscss_content +{ + struct content base; /**< Underlying content object */ + + struct content_css_data data; /**< CSS data */ +} nscss_content; + +/** * Context for import fetches */ typedef struct { @@ -44,6 +55,18 @@ typedef struct { * imports array */ } nscss_import_ctx; +static nserror nscss_create(const content_handler *handler, + lwc_string *imime_type, const http_parameter *params, + llcache_handle *llcache, const char *fallback_charset, + bool quirks, struct content **c); +static bool nscss_process_data(struct content *c, const char *data, + unsigned int size); +static bool nscss_convert(struct content *c); +static void nscss_destroy(struct content *c); +static nserror nscss_clone(const struct content *old, struct content **newc); +static bool nscss_matches_quirks(const struct content *c, bool quirks); +static content_type nscss_content_type(lwc_string *mime_type); + static void nscss_content_done(struct content_css_data *css, void *pw); static css_error nscss_handle_import(void *pw, css_stylesheet *parent, lwc_string *url, uint64_t media); @@ -55,13 +78,56 @@ static css_error nscss_register_imports(struct content_css_data *c); static css_error nscss_register_import(struct content_css_data *c, const hlcache_handle *import); +static const content_handler css_content_handler = { + nscss_create, + nscss_process_data, + nscss_convert, + NULL, + nscss_destroy, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + nscss_clone, + nscss_matches_quirks, + nscss_content_type, + false +}; + +static lwc_string *css_mime_type; static css_stylesheet *blank_import; /** - * Clean up after the CSS subsystem + * Initialise the CSS content handler */ -void css_cleanup(void) +nserror css_init(void) { + lwc_error lerror; + nserror error; + + lerror = lwc_intern_string("text/css", SLEN("text/css"), + &css_mime_type); + if (lerror != lwc_error_ok) + return NSERROR_NOMEM; + + error = content_factory_register_handler(css_mime_type, + &css_content_handler); + if (error != NSERROR_OK) + lwc_string_unref(css_mime_type); + + return error; +} + +/** + * Clean up after the CSS content handler + */ +void css_fini(void) +{ + lwc_string_unref(css_mime_type); + if (blank_import != NULL) css_stylesheet_destroy(blank_import); } @@ -73,32 +139,49 @@ void css_cleanup(void) * \param params Content-Type parameters * \return true on success, false on failure */ -bool nscss_create(struct content *c, const http_parameter *params) +nserror nscss_create(const content_handler *handler, + lwc_string *imime_type, const http_parameter *params, + llcache_handle *llcache, const char *fallback_charset, + bool quirks, struct content **c) { + nscss_content *result; const char *charset = NULL; union content_msg_data msg_data; nserror error; - /** \todo what happens about the allocator? */ - /** \todo proper error reporting */ + result = talloc_zero(0, nscss_content); + if (result == NULL) + return NSERROR_NOMEM; + + error = content__init(&result->base, handler, imime_type, + params, llcache, fallback_charset, quirks); + if (error != NSERROR_OK) { + talloc_free(result); + return error; + } /* Find charset specified on HTTP layer, if any */ error = http_parameter_list_find_item(params, "charset", &charset); if (error != NSERROR_OK || *charset == '\0') { /* No charset specified, use fallback, if any */ /** \todo libcss will take this as gospel, which is wrong */ - charset = c->fallback_charset; + charset = fallback_charset; } - if (nscss_create_css_data(&c->data.css, content__get_url(c), - charset, c->quirks, - nscss_content_done, c) != NSERROR_OK) { + error = nscss_create_css_data(&result->data, + content__get_url(&result->base), + charset, result->base.quirks, + nscss_content_done, result); + if (error != NSERROR_OK) { msg_data.error = messages_get("NoMemory"); - content_broadcast(c, CONTENT_MSG_ERROR, msg_data); - return false; + content_broadcast(&result->base, CONTENT_MSG_ERROR, msg_data); + talloc_free(result); + return error; } - return true; + *c = (struct content *) result; + + return NSERROR_OK; } /** @@ -163,10 +246,11 @@ nserror nscss_create_css_data(struct content_css_data *c, */ bool nscss_process_data(struct content *c, const char *data, unsigned int size) { + nscss_content *css = (nscss_content *) c; union content_msg_data msg_data; css_error error; - error = nscss_process_css_data(&c->data.css, data, size); + error = nscss_process_css_data(&css->data, data, size); if (error != CSS_OK && error != CSS_NEEDDATA) { msg_data.error = "?"; content_broadcast(c, CONTENT_MSG_ERROR, msg_data); @@ -198,10 +282,11 @@ css_error nscss_process_css_data(struct content_css_data *c, const char *data, */ bool nscss_convert(struct content *c) { + nscss_content *css = (nscss_content *) c; union content_msg_data msg_data; css_error error; - error = nscss_convert_css_data(&c->data.css); + error = nscss_convert_css_data(&css->data); if (error != CSS_OK) { msg_data.error = "?"; content_broadcast(c, CONTENT_MSG_ERROR, msg_data); @@ -256,7 +341,9 @@ css_error nscss_convert_css_data(struct content_css_data *c) */ void nscss_destroy(struct content *c) { - nscss_destroy_css_data(&c->data.css); + nscss_content *css = (nscss_content *) c; + + nscss_destroy_css_data(&css->data); } /** @@ -285,32 +372,75 @@ void nscss_destroy_css_data(struct content_css_data *c) free(c->charset); } -bool nscss_clone(const struct content *old, struct content *new_content) +nserror nscss_clone(const struct content *old, struct content **newc) { + const nscss_content *old_css = (const nscss_content *) old; + nscss_content *new_css; const char *data; unsigned long size; + nserror error; + + new_css = talloc_zero(0, nscss_content); + if (new_css == NULL) + return NSERROR_NOMEM; + + /* Clone content */ + error = content__clone(old, &new_css->base); + if (error != NSERROR_OK) { + content_destroy(&new_css->base); + return error; + } /* Simply replay create/process/convert */ - if (nscss_create_css_data(&new_content->data.css, - content__get_url(new_content), - old->data.css.charset, - new_content->quirks, - nscss_content_done, new_content) != NSERROR_OK) - return false; + error = nscss_create_css_data(&new_css->data, + content__get_url(&new_css->base), + old_css->data.charset, + new_css->base.quirks, + nscss_content_done, new_css); + if (error != NSERROR_OK) { + content_destroy(&new_css->base); + return error; + } - data = content__get_source_data(new_content, &size); + data = content__get_source_data(&new_css->base, &size); if (size > 0) { - if (nscss_process_data(new_content, data, size) == false) - return false; + if (nscss_process_data(&new_css->base, data, size) == false) { + content_destroy(&new_css->base); + return NSERROR_CLONE_FAILED; + } } if (old->status == CONTENT_STATUS_READY || old->status == CONTENT_STATUS_DONE) { - if (nscss_convert(new_content) == false) - return false; + if (nscss_convert(&new_css->base) == false) { + content_destroy(&new_css->base); + return NSERROR_CLONE_FAILED; + } } - return true; + *newc = (struct content *) new_css; + + return NSERROR_OK; +} + +bool nscss_matches_quirks(const struct content *c, bool quirks) +{ + return c->quirks == quirks; +} + +/** + * Retrieve the stylesheet object associated with a CSS content + * + * \param h Stylesheet content + * \return Pointer to stylesheet object + */ +css_stylesheet *nscss_get_stylesheet(struct hlcache_handle *h) +{ + nscss_content *c = (nscss_content *) hlcache_handle_get_content(h); + + assert(c != NULL); + + return c->data.sheet; } /** @@ -322,15 +452,25 @@ bool nscss_clone(const struct content *old, struct content *new_content) */ struct nscss_import *nscss_get_imports(hlcache_handle *h, uint32_t *n) { - struct content *c = hlcache_handle_get_content(h); + nscss_content *c = (nscss_content *) hlcache_handle_get_content(h); assert(c != NULL); - assert(c->type == CONTENT_CSS); assert(n != NULL); - *n = c->data.css.import_count; + *n = c->data.import_count; - return c->data.css.imports; + return c->data.imports; +} + +/** + * Compute the type of a content + * + * \param mime_type MIME type + * \return CONTENT_CSS + */ +content_type nscss_content_type(lwc_string *mime_type) +{ + return CONTENT_CSS; } /***************************************************************************** @@ -394,7 +534,7 @@ void nscss_content_done(struct content_css_data *css, void *pw) css_error nscss_handle_import(void *pw, css_stylesheet *parent, lwc_string *url, uint64_t media) { - static const content_type accept[] = { CONTENT_CSS, CONTENT_UNKNOWN }; + content_type accept = CONTENT_CSS; struct content_css_data *c = pw; nscss_import_ctx *ctx; hlcache_child_context child; @@ -478,9 +618,6 @@ nserror nscss_import(hlcache_handle *handle, switch (event->type) { case CONTENT_MSG_LOADING: - if (content_get_type(handle) != CONTENT_CSS) { - assert(0 && "Non-CSS type unexpected"); - } break; case CONTENT_MSG_READY: break; @@ -589,8 +726,9 @@ css_error nscss_register_import(struct content_css_data *c, css_error error; if (import != NULL) { - struct content *s = hlcache_handle_get_content(import); - sheet = s->data.css.sheet; + nscss_content *s = + (nscss_content *) hlcache_handle_get_content(import); + sheet = s->data.sheet; } else { /* Create a blank sheet if needed. */ if (blank_import == NULL) { @@ -61,17 +61,8 @@ struct nscss_import { uint64_t media; /**< Media types that sheet applies to */ }; -void css_cleanup(void); - -bool nscss_create(struct content *c, const struct http_parameter *params); - -bool nscss_process_data(struct content *c, const char *data, unsigned int size); - -bool nscss_convert(struct content *c); - -void nscss_destroy(struct content *c); - -bool nscss_clone(const struct content *old, struct content *new_content); +nserror css_init(void); +void css_fini(void); nserror nscss_create_css_data(struct content_css_data *c, const char *url, const char *charset, bool quirks, @@ -81,6 +72,7 @@ css_error nscss_process_css_data(struct content_css_data *c, const char *data, css_error nscss_convert_css_data(struct content_css_data *c); void nscss_destroy_css_data(struct content_css_data *c); +css_stylesheet *nscss_get_stylesheet(struct hlcache_handle *h); struct nscss_import *nscss_get_imports(struct hlcache_handle *h, uint32_t *n); #endif diff --git a/css/select.c b/css/select.c index d4d6361b7..7e1af71d7 100644 --- a/css/select.c +++ b/css/select.c @@ -99,7 +99,7 @@ static bool parse_dimension(const char *data, bool strict, static bool parse_number(const char *data, bool non_negative, bool real, css_fixed *value, size_t *consumed); -static css_computed_style *nscss_get_initial_style(struct content *html, +static css_computed_style *nscss_get_initial_style(nscss_select_ctx *ctx, css_allocator_fn, void *pw); static bool isWhitespace(char c); @@ -211,7 +211,7 @@ css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len, /** * Get a style selection results (partial computed styles) for an element * - * \param html HTML document + * \param ctx CSS selection context * \param n Element to select for * \param media Permitted media types * \param inline_style Inline style associated with element, or NULL @@ -220,17 +220,15 @@ css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len, * \return Pointer to selection results (containing partial computed styles), * or NULL on failure */ -css_select_results *nscss_get_style(struct content *html, xmlNode *n, +css_select_results *nscss_get_style(nscss_select_ctx *ctx, xmlNode *n, uint64_t media, const css_stylesheet *inline_style, css_allocator_fn alloc, void *pw) { css_select_results *styles; css_error error; - assert(html->type == CONTENT_HTML); - - error = css_select_style(html->data.html.select_ctx, n, media, - inline_style, &selection_handler, html, &styles); + error = css_select_style(ctx->ctx, n, media, inline_style, + &selection_handler, ctx, &styles); if (error != CSS_OK) { return NULL; } @@ -241,24 +239,22 @@ css_select_results *nscss_get_style(struct content *html, xmlNode *n, /** * Get an initial style * - * \param html HTML document + * \param ctx CSS selection context * \param alloc Memory allocation function * \param pw Private word for allocator * \return Pointer to partial computed style, or NULL on failure */ -css_computed_style *nscss_get_initial_style(struct content *html, +css_computed_style *nscss_get_initial_style(nscss_select_ctx *ctx, css_allocator_fn alloc, void *pw) { css_computed_style *style; css_error error; - assert(html->type == CONTENT_HTML); - error = css_computed_style_create(alloc, pw, &style); if (error != CSS_OK) return NULL; - error = css_computed_style_initialise(style, &selection_handler, html); + error = css_computed_style_initialise(style, &selection_handler, ctx); if (error != CSS_OK) { css_computed_style_destroy(style); return NULL; @@ -270,22 +266,20 @@ css_computed_style *nscss_get_initial_style(struct content *html, /** * Get a blank style * - * \param html HTML document + * \param ctx CSS selection context * \param parent Parent style to cascade inherited properties from * \param alloc Memory allocation function * \param pw Private word for allocator * \return Pointer to blank style, or NULL on failure */ -css_computed_style *nscss_get_blank_style(struct content *html, +css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx, const css_computed_style *parent, css_allocator_fn alloc, void *pw) { css_computed_style *partial; css_error error; - assert(html->type == CONTENT_HTML); - - partial = nscss_get_initial_style(html, alloc, pw); + partial = nscss_get_initial_style(ctx, alloc, pw); if (partial == NULL) return NULL; @@ -877,7 +871,7 @@ css_error node_has_name(void *pw, void *node, css_error node_has_class(void *pw, void *node, lwc_string *name, bool *match) { - struct content *html = pw; + nscss_select_ctx *ctx = pw; xmlNode *n = node; xmlAttr *class; xmlChar *value = NULL; @@ -888,7 +882,7 @@ css_error node_has_class(void *pw, void *node, int (*cmp)(const char *, const char *, size_t); /* Class names are case insensitive in quirks mode */ - if (html->data.html.quirks == BINDING_QUIRKS_MODE_FULL) + if (ctx->quirks) cmp = strncasecmp; else cmp = strncmp; @@ -1418,7 +1412,7 @@ css_error node_is_visited(void *pw, void *node, bool *match) /** \todo Implement visted check in a more performant way */ #ifdef SUPPORT_VISITED - struct content *html = pw; + nscss_select_ctx *ctx = pw; xmlNode *n = node; if (strcasecmp((const char *) n->name, "a") == 0) { @@ -1430,8 +1424,7 @@ css_error node_is_visited(void *pw, void *node, bool *match) return CSS_OK; /* Make href absolute */ - res = url_join((const char *) href, - html->data.html.base_url, &url); + res = url_join((const char *) href, ctx->base_url, &url); xmlFree(href); @@ -1632,7 +1625,7 @@ css_error node_is_lang(void *pw, void *node, css_error node_presentational_hint(void *pw, void *node, uint32_t property, css_hint *hint) { - struct content *html = pw; + nscss_select_ctx *ctx = pw; xmlNode *n = node; if (property == CSS_PROP_BACKGROUND_IMAGE) { @@ -1644,8 +1637,7 @@ css_error node_presentational_hint(void *pw, void *node, return CSS_PROPERTY_NOT_SET; - res = url_join((const char *) bg, - html->data.html.base_url, &url); + res = url_join((const char *) bg, ctx->base_url, &url); xmlFree(bg); @@ -1707,7 +1699,7 @@ css_error node_presentational_hint(void *pw, void *node, css_error error; bool is_link, is_visited; - error = node_is_link(html, n, &is_link); + error = node_is_link(ctx, n, &is_link); if (error != CSS_OK) return error; @@ -1720,7 +1712,7 @@ css_error node_presentational_hint(void *pw, void *node, break; } - error = node_is_visited(html, n, &is_visited); + error = node_is_visited(ctx, n, &is_visited); if (error != CSS_OK) return error; diff --git a/css/select.h b/css/select.h index 21b53867d..c90e7f7a4 100644 --- a/css/select.h +++ b/css/select.h @@ -27,15 +27,25 @@ struct content; +/** + * Selection context + */ +typedef struct nscss_select_ctx +{ + css_select_ctx *ctx; + bool quirks; + const char *base_url; +} nscss_select_ctx; + css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len, const char *charset, const char *url, bool allow_quirks, css_allocator_fn alloc, void *pw); -css_select_results *nscss_get_style(struct content *html, xmlNode *n, +css_select_results *nscss_get_style(nscss_select_ctx *ctx, xmlNode *n, uint64_t media, const css_stylesheet *inline_style, css_allocator_fn alloc, void *pw); -css_computed_style *nscss_get_blank_style(struct content *html, +css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx, const css_computed_style *parent, css_allocator_fn alloc, void *pw); |