diff options
Diffstat (limited to 'render/html.c')
-rw-r--r-- | render/html.c | 191 |
1 files changed, 118 insertions, 73 deletions
diff --git a/render/html.c b/render/html.c index 1905e8bc3..bad7ff2e2 100644 --- a/render/html.c +++ b/render/html.c @@ -61,7 +61,8 @@ static void html_convert_css_callback(content_msg msg, struct content *css, static bool html_meta_refresh(struct content *c, xmlNode *head); static bool html_head(struct content *c, xmlNode *head); static bool html_find_stylesheets(struct content *c, xmlNode *html); -static bool html_process_style_element(struct content *c, xmlNode *style); +static bool html_process_style_element(struct content *c, unsigned int index, + xmlNode *style); static void html_object_callback(content_msg msg, struct content *object, intptr_t p1, intptr_t p2, union content_msg_data data); static void html_object_done(struct box *box, struct content *object, @@ -92,6 +93,18 @@ static const char empty_document[] = "</body>" "</html>"; +/** + * Allocator + * + * \param ptr Pointer to reallocate, or NULL for new allocation + * \param size Number of bytes requires + * \param pw Allocation context + * \return Pointer to allocated block, or NULL on failure + */ +static void *myrealloc(void *ptr, size_t len, void *pw) +{ + return realloc(ptr, len); +} /** * Create a CONTENT_HTML. @@ -100,15 +113,19 @@ static const char empty_document[] = * created. */ -bool html_create(struct content *c, const char *params[]) +bool html_create(struct content *c, struct content *parent, + const char *params[]) { unsigned int i; struct content_html_data *html = &c->data.html; union content_msg_data msg_data; binding_error error; + lwc_context *dict; + lwc_error lerror; html->parser_binding = NULL; html->document = 0; + html->quirks = BINDING_QUIRKS_MODE_NONE; html->encoding = 0; html->base_url = c->url; html->base_target = NULL; @@ -116,8 +133,7 @@ bool html_create(struct content *c, const char *params[]) html->background_colour = NS_TRANSPARENT; html->stylesheet_count = 0; html->stylesheet_content = 0; - html->style = 0; - html->working_stylesheet = 0; + html->select_ctx = NULL; html->object_count = 0; html->object = 0; html->forms = 0; @@ -130,6 +146,14 @@ bool html_create(struct content *c, const char *params[]) html->box = 0; html->font_func = &nsfont; + lerror = lwc_create_context(myrealloc, c, &dict); + if (lerror != lwc_error_ok) { + error = BINDING_NOMEM; + goto error; + } + + html->dict = lwc_context_ref(dict); + for (i = 0; params[i]; i += 2) { if (strcasecmp(params[i], "charset") == 0) { html->encoding = talloc_strdup(c, params[i + 1]); @@ -343,7 +367,8 @@ bool html_convert(struct content *c, int width, int height) } c->data.html.document = - binding_get_document(c->data.html.parser_binding); + binding_get_document(c->data.html.parser_binding, + &c->data.html.quirks); /*xmlDebugDumpDocument(stderr, c->data.html.document);*/ if (!c->data.html.document) { @@ -467,7 +492,7 @@ bool html_convert(struct content *c, int width, int height) option_min_reflow_period : time_taken * 1.25)); LOG(("Scheduling relayout no sooner than %dcs", c->reformat_time - wallclock())); - /*box_dump(c->data.html.layout->children, 0);*/ + /*box_dump(stderr, c->data.html.layout->children, 0);*/ /* Destroy the parser binding */ binding_destroy_tree(c->data.html.parser_binding); @@ -778,16 +803,17 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) union content_msg_data msg_data; url_func_result res; struct content **stylesheet_content; + css_error error; /* stylesheet 0 is the base style sheet, - * stylesheet 1 is the adblocking stylesheet, - * stylesheet 2 is any <style> elements */ + * stylesheet 1 is the quirks mode style sheet, + * stylesheet 2 is the adblocking stylesheet */ c->data.html.stylesheet_content = talloc_array(c, struct content *, STYLESHEET_START); if (!c->data.html.stylesheet_content) goto no_memory; - c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] = 0; - c->data.html.stylesheet_content[STYLESHEET_STYLE] = 0; + c->data.html.stylesheet_content[STYLESHEET_QUIRKS] = NULL; + c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] = NULL; c->data.html.stylesheet_count = STYLESHEET_START; c->active = 0; @@ -805,6 +831,22 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) STYLESHEET_BASE, c->width, c->height, 0, 0, false, c); + if (c->data.html.quirks == BINDING_QUIRKS_MODE_FULL) { + c->data.html.stylesheet_content[STYLESHEET_QUIRKS] = + fetchcache(quirks_stylesheet_url, + html_convert_css_callback, (intptr_t) c, + STYLESHEET_QUIRKS, c->width, c->height, + true, 0, 0, false, false); + if (c->data.html.stylesheet_content[STYLESHEET_QUIRKS] == NULL) + goto no_memory; + c->active++; + fetchcache_go(c->data.html. + stylesheet_content[STYLESHEET_QUIRKS], + c->url, html_convert_css_callback, + (intptr_t) c, STYLESHEET_QUIRKS, c->width, + c->height, 0, 0, false, c); + } + if (option_block_ads) { c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] = fetchcache(adblock_stylesheet_url, @@ -931,31 +973,14 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) i++; } else if (strcmp((const char *) node->name, "style") == 0) { - if (!html_process_style_element(c, node)) + if (!html_process_style_element(c, i, node)) return false; + i++; } } c->data.html.stylesheet_count = i; - if (c->data.html.stylesheet_content[STYLESHEET_STYLE] != 0) { - if (css_convert(c->data.html. - stylesheet_content[STYLESHEET_STYLE], c->width, - c->height)) { - if (!content_add_user(c->data.html. - stylesheet_content[STYLESHEET_STYLE], - html_convert_css_callback, - (intptr_t) c, STYLESHEET_STYLE)) { - /* no memory */ - c->data.html.stylesheet_content[STYLESHEET_STYLE] = 0; - goto no_memory; - } - } else { - /* conversion failed */ - c->data.html.stylesheet_content[STYLESHEET_STYLE] = 0; - } - } - /* complete the fetches */ while (c->active != 0) { if (c->active != last_active) { @@ -974,29 +999,23 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) return false; } - assert(c->data.html.stylesheet_content[STYLESHEET_BASE]); - css_set_origin(c->data.html.stylesheet_content[STYLESHEET_BASE], - CSS_ORIGIN_UA); - - /* any of our other stylesheet pointers could be NULL at this point if - * the CSS file(s) failed to load/fetch */ - if (c->data.html.stylesheet_content[STYLESHEET_ADBLOCK]) - css_set_origin(c->data.html.stylesheet_content[ - STYLESHEET_ADBLOCK], CSS_ORIGIN_UA); - if (c->data.html.stylesheet_content[STYLESHEET_STYLE]) - css_set_origin(c->data.html.stylesheet_content[ - STYLESHEET_STYLE], CSS_ORIGIN_AUTHOR); - for (i = STYLESHEET_START; i != c->data.html.stylesheet_count; i++) - if (c->data.html.stylesheet_content[i]) - css_set_origin(c->data.html.stylesheet_content[i], - CSS_ORIGIN_AUTHOR); - - c->data.html.working_stylesheet = css_make_working_stylesheet( - c->data.html.stylesheet_content, - c->data.html.stylesheet_count); - if (!c->data.html.working_stylesheet) + /* Create selection context */ + error = css_select_ctx_create(myrealloc, c, &c->data.html.select_ctx); + if (error != CSS_OK) goto no_memory; + /* Add sheets to it */ + for (i = STYLESHEET_BASE; i != c->data.html.stylesheet_count; i++) { + if (c->data.html.stylesheet_content[i]) { + error = css_select_ctx_append_sheet( + c->data.html.select_ctx, + c->data.html.stylesheet_content[i]-> + data.css.sheet); + if (error != CSS_OK) + goto no_memory; + } + } + return true; no_memory: @@ -1010,15 +1029,19 @@ no_memory: * Process an inline stylesheet in the document. * * \param c content structure + * \param index Index of stylesheet in stylesheet_content array * \param style xml node of style element * \return true on success, false if an error occurred */ -bool html_process_style_element(struct content *c, xmlNode *style) +bool html_process_style_element(struct content *c, unsigned int index, + xmlNode *style) { xmlNode *child; char *type, *media, *data; union content_msg_data msg_data; + struct content **stylesheet_content; + const char *params[] = { 0 }; /* type='text/css', or not present (invalid but common) */ if ((type = (char *) xmlGetProp(style, (const xmlChar *) "type"))) { @@ -1039,20 +1062,24 @@ bool html_process_style_element(struct content *c, xmlNode *style) xmlFree(media); } + /* Extend array */ + stylesheet_content = talloc_realloc(c, c->data.html.stylesheet_content, + struct content *, index + 1); + if (stylesheet_content == NULL) + goto no_memory; + + c->data.html.stylesheet_content = stylesheet_content; + /* create stylesheet */ - if (c->data.html.stylesheet_content[STYLESHEET_STYLE] == 0) { - const char *params[] = { 0 }; - c->data.html.stylesheet_content[STYLESHEET_STYLE] = - content_create(c->data.html.base_url); - if (!c->data.html.stylesheet_content[STYLESHEET_STYLE]) - goto no_memory; - if (!content_set_type(c->data.html. - stylesheet_content[STYLESHEET_STYLE], - CONTENT_CSS, "text/css", params)) - /** \todo not necessarily caused by - * memory exhaustion */ - goto no_memory; - } + c->data.html.stylesheet_content[index] = + content_create(c->data.html.base_url); + if (c->data.html.stylesheet_content[index] == NULL) + goto no_memory; + if (!content_set_type(c->data.html.stylesheet_content[index], + CONTENT_CSS, "text/css", params, c)) + /** \todo not necessarily caused by + * memory exhaustion */ + goto no_memory; /* can't just use xmlNodeGetContent(style), because that won't * give the content of comments which may be used to 'hide' @@ -1060,7 +1087,7 @@ bool html_process_style_element(struct content *c, xmlNode *style) for (child = style->children; child != 0; child = child->next) { data = (char *) xmlNodeGetContent(child); if (!content_process_data(c->data.html. - stylesheet_content[STYLESHEET_STYLE], + stylesheet_content[index], data, strlen(data))) { xmlFree(data); /** \todo not necessarily caused by @@ -1070,6 +1097,21 @@ bool html_process_style_element(struct content *c, xmlNode *style) xmlFree(data); } + /* Convert the content */ + if (nscss_convert(c->data.html.stylesheet_content[index], c->width, + c->height)) { + if (!content_add_user(c->data.html.stylesheet_content[index], + html_convert_css_callback, + (intptr_t) c, index)) { + /* no memory */ + c->data.html.stylesheet_content[index] = NULL; + goto no_memory; + } + } else { + /* conversion failed */ + c->data.html.stylesheet_content[index] = NULL; + } + return true; no_memory: @@ -1181,7 +1223,7 @@ void html_convert_css_callback(content_msg msg, struct content *css, * \return true on success, false on memory exhaustion */ -bool html_fetch_object(struct content *c, char *url, struct box *box, +bool html_fetch_object(struct content *c, const char *url, struct box *box, const content_type *permitted_types, int available_width, int available_height, bool background) @@ -1693,10 +1735,10 @@ void html_reformat(struct content *c, int width, int height) /* width and height are at least margin box of document */ c->width = layout->x + layout->padding[LEFT] + layout->width + - layout->padding[RIGHT] + layout->border[RIGHT] + + layout->padding[RIGHT] + layout->border[RIGHT].width + layout->margin[RIGHT]; c->height = layout->y + layout->padding[TOP] + layout->height + - layout->padding[BOTTOM] + layout->border[BOTTOM] + + layout->padding[BOTTOM] + layout->border[BOTTOM].width + layout->margin[BOTTOM]; /* if boxes overflow right or bottom edge, expand to contain it */ @@ -1757,6 +1799,12 @@ void html_destroy(struct content *c) c->data.html.iframe = NULL; } + /* Destroy selection context */ + if (c->data.html.select_ctx) { + css_select_ctx_destroy(c->data.html.select_ctx); + c->data.html.select_ctx = NULL; + } + /* Free stylesheets */ if (c->data.html.stylesheet_count) { for (i = 0; i != c->data.html.stylesheet_count; i++) { @@ -1768,11 +1816,6 @@ void html_destroy(struct content *c) } } - talloc_free(c->data.html.working_stylesheet); - - /*if (c->data.html.style) - css_free_style(c->data.html.style);*/ - /* Free objects */ for (i = 0; i != c->data.html.object_count; i++) { LOG(("object %i %p", i, c->data.html.object[i].content)); @@ -1784,6 +1827,8 @@ void html_destroy(struct content *c) c->data.html.object[i].content); } } + + lwc_context_unref(c->data.html.dict); } void html_destroy_frameset(struct content_html_frames *frameset) { |