summaryrefslogtreecommitdiff
path: root/css
diff options
context:
space:
mode:
Diffstat (limited to 'css')
-rw-r--r--css/css.c214
-rw-r--r--css/css.h14
-rw-r--r--css/select.c46
-rw-r--r--css/select.h14
4 files changed, 210 insertions, 78 deletions
diff --git a/css/css.c b/css/css.c
index b03f2342b..b27debd5a 100644
--- a/css/css.c
+++ b/css/css.c
@@ -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) {
diff --git a/css/css.h b/css/css.h
index d2f1191e2..28008664f 100644
--- a/css/css.h
+++ b/css/css.h
@@ -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);