diff options
Diffstat (limited to 'render')
-rw-r--r-- | render/box_construct.c | 4 | ||||
-rw-r--r-- | render/box_normalise.c | 14 | ||||
-rw-r--r-- | render/html.c | 513 | ||||
-rw-r--r-- | render/html.h | 7 | ||||
-rw-r--r-- | render/html_internal.h | 21 | ||||
-rw-r--r-- | render/html_script.c | 339 | ||||
-rw-r--r-- | render/hubbub_binding.c | 1325 | ||||
-rw-r--r-- | render/libdom_binding.c | 126 | ||||
-rw-r--r-- | render/parser_binding.h | 63 |
9 files changed, 478 insertions, 1934 deletions
diff --git a/render/box_construct.c b/render/box_construct.c index c09563d89..5f8b092c5 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -1426,7 +1426,7 @@ css_select_results *box_get_style(html_content *c, dom_string_byte_length(s), c->encoding, nsurl_access(content_get_url(&c->base)), - c->quirks != BINDING_QUIRKS_MODE_NONE, + c->quirks != DOM_DOCUMENT_QUIRKS_MODE_NONE, box_style_alloc, NULL); dom_string_unref(s); @@ -1437,7 +1437,7 @@ css_select_results *box_get_style(html_content *c, /* Populate selection context */ ctx.ctx = c->select_ctx; - ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL); + ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL); ctx.base_url = c->base_url; ctx.universal = c->universal; diff --git a/render/box_normalise.c b/render/box_normalise.c index fb378d3e7..19a1cbc25 100644 --- a/render/box_normalise.c +++ b/render/box_normalise.c @@ -152,7 +152,7 @@ bool box_normalise_block(struct box *block, html_content *c) assert(block->style != NULL); ctx.ctx = c->select_ctx; - ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL); + ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL); ctx.base_url = c->base_url; ctx.universal = c->universal; @@ -254,7 +254,7 @@ bool box_normalise_table(struct box *table, html_content * c) assert(table->style != NULL); ctx.ctx = c->select_ctx; - ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL); + ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL); ctx.base_url = c->base_url; ctx.universal = c->universal; @@ -341,7 +341,7 @@ bool box_normalise_table(struct box *table, html_content * c) assert(table->style != NULL); ctx.ctx = c->select_ctx; - ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL); + ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL); ctx.base_url = c->base_url; ctx.universal = c->universal; @@ -477,7 +477,7 @@ bool box_normalise_table_spans(struct box *table, struct span_info *spans, ctx.ctx = c->select_ctx; ctx.quirks = (c->quirks == - BINDING_QUIRKS_MODE_FULL); + DOM_DOCUMENT_QUIRKS_MODE_FULL); ctx.base_url = c->base_url; ctx.universal = c->universal; @@ -587,7 +587,7 @@ bool box_normalise_table_row_group(struct box *row_group, assert(row_group->style != NULL); ctx.ctx = c->select_ctx; - ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL); + ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL); ctx.base_url = c->base_url; ctx.universal = c->universal; @@ -662,7 +662,7 @@ bool box_normalise_table_row_group(struct box *row_group, assert(row_group->style != NULL); ctx.ctx = c->select_ctx; - ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL); + ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL); ctx.base_url = c->base_url; ctx.universal = c->universal; @@ -732,7 +732,7 @@ bool box_normalise_table_row(struct box *row, assert(row->style != NULL); ctx.ctx = c->select_ctx; - ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL); + ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL); ctx.base_url = c->base_url; ctx.universal = c->universal; diff --git a/render/html.c b/render/html.c index 996bfc3a5..8c11f35b9 100644 --- a/render/html.c +++ b/render/html.c @@ -28,8 +28,6 @@ #include <strings.h> #include <stdlib.h> -#include <dom/dom.h> - #include "utils/config.h" #include "content/content_protected.h" #include "content/fetch.h" @@ -38,7 +36,6 @@ #include "desktop/options.h" #include "desktop/selection.h" #include "desktop/scrollbar.h" -#include "javascript/js.h" #include "image/bitmap.h" #include "render/box.h" #include "render/font.h" @@ -86,15 +83,15 @@ static dom_string *html_dom_string_head; static dom_string *html_dom_string_rel; dom_string *html_dom_string_href; static dom_string *html_dom_string_hreflang; -static dom_string *html_dom_string_type; +dom_string *html_dom_string_type; static dom_string *html_dom_string_media; static dom_string *html_dom_string_sizes; static dom_string *html_dom_string_title; static dom_string *html_dom_string_base; static dom_string *html_dom_string_link; static dom_string *html_dom_string_script; -static dom_string *html_dom_string_text_javascript; -static dom_string *html_dom_string_src; +dom_string *html_dom_string_text_javascript; +dom_string *html_dom_string_src; dom_string *html_dom_string_target; static dom_string *html_dom_string__parent; static dom_string *html_dom_string__self; @@ -117,107 +114,6 @@ dom_string *html_dom_string_circle; dom_string *html_dom_string_poly; dom_string *html_dom_string_polygon; -typedef bool (script_handler_t)(struct jscontext *jscontext, const char *data, size_t size) ; - - -static script_handler_t *select_script_handler(content_type ctype) -{ - if (ctype == CONTENT_JS) { - return js_exec; - } - return NULL; -} - - -/* attempt to progress script execution - * - * execute scripts using algorithm found in: - * http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element - * - */ -static bool html_scripts_exec(html_content *c) -{ - unsigned int i; - struct html_script *s; - script_handler_t *script_handler; - - if (c->jscontext == NULL) - return false; - - for (i = 0, s = c->scripts; i != c->scripts_count; i++, s++) { - if (s->already_started) { - continue; - } - - assert((s->type == HTML_SCRIPT_EXTERNAL) || - (s->type == HTML_SCRIPT_INTERNAL)); - - if (s->type == HTML_SCRIPT_EXTERNAL) { - /* ensure script content is present */ - if (s->data.external == NULL) - continue; - - /* ensure script content fetch status is not an error */ - if (content_get_status(s->data.external) == CONTENT_STATUS_ERROR) - continue; - - /* ensure script handler for content type */ - script_handler = select_script_handler(content_get_type(s->data.external)); - if (script_handler == NULL) - continue; /* unsupported type */ - - if (content_get_status(s->data.external) == CONTENT_STATUS_DONE) { - /* external script is now available */ - const char *data; - unsigned long size; - data = content_get_source_data(s->data.external, &size ); - script_handler(c->jscontext, data, size); - - s->already_started = true; - - } else { - /* script not yet available */ - - /* check if deferable or asynchronous */ - if (!s->defer && !s->async) { - break; - } - } - } - } - - return true; -} - -/* create new html script entry */ -static struct html_script * -html_process_new_script(html_content *c, enum html_script_type type) -{ - struct html_script *nscript; - /* add space for new script entry */ - nscript = realloc(c->scripts, - sizeof(struct html_script) * (c->scripts_count + 1)); - if (nscript == NULL) { - return NULL; - } - - c->scripts = nscript; - - /* increment script entry count */ - nscript = &c->scripts[c->scripts_count]; - c->scripts_count++; - - nscript->already_started = false; - nscript->parser_inserted = false; - nscript->force_async = true; - nscript->ready_exec = false; - nscript->async = false; - nscript->defer = false; - - nscript->type = type; - - return nscript; -} static void html_destroy_objects(html_content *html) { @@ -293,8 +189,8 @@ static void html_box_convert_done(html_content *c, bool success) /*imagemap_dump(c);*/ /* Destroy the parser binding */ - binding_destroy_tree(c->parser_binding); - c->parser_binding = NULL; + dom_hubbub_parser_destroy(c->parser); + c->parser = NULL; content_set_ready(&c->base); @@ -309,7 +205,7 @@ static void html_box_convert_done(html_content *c, bool success) * * \param c Content to convert */ -static void html_finish_conversion(html_content *c) +void html_finish_conversion(html_content *c) { union content_msg_data msg_data; dom_exception exc; /* returned by libdom functions */ @@ -400,217 +296,17 @@ static void html_finish_conversion(html_content *c) } -/** - * Callback for fetchcache() for linked stylesheets. - */ - -static nserror -html_convert_script_callback(hlcache_handle *script, - const hlcache_event *event, - void *pw) -{ - html_content *parent = pw; - unsigned int i; - struct html_script *s; - - /* Find script */ - for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) { - if (s->type == HTML_SCRIPT_EXTERNAL && - s->data.external == script) - break; - } - - assert(i != parent->scripts_count); - - switch (event->type) { - case CONTENT_MSG_LOADING: - break; - - case CONTENT_MSG_READY: - break; - - case CONTENT_MSG_DONE: - LOG(("script %d done '%s'", i, - nsurl_access(hlcache_handle_get_url(script)))); - parent->base.active--; - LOG(("%d fetches active", parent->base.active)); - - /* script finished loading so try and continue execution */ - html_scripts_exec(parent); - break; - - case CONTENT_MSG_ERROR: - LOG(("script %s failed: %s", - nsurl_access(hlcache_handle_get_url(script)), - event->data.error)); - hlcache_handle_release(script); - s->data.external = NULL; - parent->base.active--; - LOG(("%d fetches active", parent->base.active)); - content_add_error(&parent->base, "?", 0); - - /* script failed loading so try and continue execution */ - html_scripts_exec(parent); - - break; - - case CONTENT_MSG_STATUS: - html_set_status(parent, content_get_status_message(script)); - content_broadcast(&parent->base, CONTENT_MSG_STATUS, - event->data); - break; - - default: - assert(0); - } - - if (parent->base.active == 0) - html_finish_conversion(parent); - - return NSERROR_OK; -} - -/** process script node - * - * - */ -static dom_hubbub_error -html_process_script(void *ctx, dom_node *node) -{ - html_content *c = (html_content *)ctx; - dom_exception exc; /* returned by libdom functions */ - dom_string *src, *script, *mimetype; - struct html_script *nscript; - union content_msg_data msg_data; - - /* ensure javascript context is available */ - if (c->jscontext == NULL) { - union content_msg_data msg_data; - - msg_data.jscontext = &c->jscontext; - content_broadcast(&c->base, CONTENT_MSG_GETCTX, msg_data); - LOG(("javascript context %p ", c->jscontext)); - if (c->jscontext == NULL) { - /* no context and it could not be created, abort */ - return DOM_HUBBUB_OK; - } - } - - LOG(("content %p parser %p node %p",c,c->parser_binding, node)); - - exc = dom_element_get_attribute(node, html_dom_string_type, &mimetype); - if (exc != DOM_NO_ERR || mimetype == NULL) { - mimetype = dom_string_ref(html_dom_string_text_javascript); - } - - exc = dom_element_get_attribute(node, html_dom_string_src, &src); - if (exc != DOM_NO_ERR || src == NULL) { - struct lwc_string_s *lwcmimetype; - script_handler_t *script_handler; - - /* does not appear to be a src so script is inline content */ - exc = dom_node_get_text_content(node, &script); - if ((exc != DOM_NO_ERR) || (script == NULL)) { - dom_string_unref(mimetype); - return DOM_HUBBUB_OK; /* no contents, skip */ - } - - nscript = html_process_new_script(c, HTML_STYLESHEET_INTERNAL); - if (nscript == NULL) { - dom_string_unref(mimetype); - dom_string_unref(script); - goto html_process_script_no_memory; - } - - nscript->data.internal = script; - nscript->mimetype = mimetype; - nscript->already_started = true; - - /* charset (encoding) */ - - /* ensure script handler for content type */ - dom_string_intern(mimetype, &lwcmimetype); - script_handler = select_script_handler(content_factory_type_from_mime_type(lwcmimetype)); - lwc_string_unref(lwcmimetype); - - if (script_handler != NULL) { - script_handler(c->jscontext, - dom_string_data(script), - dom_string_byte_length(script)); - } - - - } else { - /* script with a src tag */ - nserror ns_error; - nsurl *joined; - hlcache_child_context child; - - - nscript = html_process_new_script(c, HTML_STYLESHEET_EXTERNAL); - if (nscript == NULL) { - dom_string_unref(src); - dom_string_unref(mimetype); - goto html_process_script_no_memory; - } - - /* charset (encoding) */ - - ns_error = nsurl_join(c->base_url, dom_string_data(src), &joined); - dom_string_unref(src); - if (ns_error != NSERROR_OK) { - dom_string_unref(mimetype); - goto html_process_script_no_memory; - } - - nscript->mimetype = mimetype; /* keep reference to mimetype */ - - LOG(("script %i '%s'", c->scripts_count, nsurl_access(joined))); - - child.charset = c->encoding; - child.quirks = c->base.quirks; - - ns_error = hlcache_handle_retrieve(joined, - 0, - content_get_url(&c->base), - NULL, - html_convert_script_callback, - c, - &child, - CONTENT_SCRIPT, - &nscript->data.external); - - nsurl_unref(joined); - - if (ns_error != NSERROR_OK) { - goto html_process_script_no_memory; - } - - c->base.active++; /* ensure base content knows the fetch is active */ - LOG(("%d fetches active", c->base.active)); - - } - html_scripts_exec(c); - - return DOM_HUBBUB_OK; - -html_process_script_no_memory: - msg_data.error = messages_get("NoMemory"); - content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); - return DOM_HUBBUB_NOMEM; -} static nserror html_create_html_data(html_content *c, const http_parameter *params) { lwc_string *charset; union content_msg_data msg_data; - binding_error error; nserror nerror; - c->parser_binding = NULL; + c->parser = NULL; c->document = NULL; - c->quirks = BINDING_QUIRKS_MODE_NONE; + c->quirks = DOM_DOCUMENT_QUIRKS_MODE_NONE; c->encoding = NULL; c->base_url = nsurl_ref(content_get_url(&c->base)); c->base_target = NULL; @@ -637,8 +333,10 @@ html_create_html_data(html_content *c, const http_parameter *params) c->jscontext = NULL; if (lwc_intern_string("*", SLEN("*"), &c->universal) != lwc_error_ok) { - error = BINDING_NOMEM; - goto error; + msg_data.error = messages_get("NoMemory"); + content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); + + return NSERROR_NOMEM; } selection_prepare(&c->sel, (struct content *)c, true); @@ -650,60 +348,56 @@ html_create_html_data(html_content *c, const http_parameter *params) lwc_string_unref(charset); if (c->encoding == NULL) { - error = BINDING_NOMEM; - goto error; + lwc_string_unref(c->universal); + c->universal = NULL; + + msg_data.error = messages_get("NoMemory"); + content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); + + return NSERROR_NOMEM; + } - c->encoding_source = ENCODING_SOURCE_HEADER; + c->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_HEADER; } /* Create the parser binding */ - error = binding_create_tree(&c->parser_binding, - c->encoding, - nsoption_bool(enable_javascript), - html_process_script, - c); - if (error == BINDING_BADENCODING && c->encoding != NULL) { + c->parser = dom_hubbub_parser_create(c->encoding, + true, + nsoption_bool(enable_javascript), + NULL, + html_process_script, + c); + if ((c->parser == NULL) && (c->encoding != NULL)) { /* Ok, we don't support the declared encoding. Bailing out * isn't exactly user-friendly, so fall back to autodetect */ talloc_free(c->encoding); c->encoding = NULL; - error = binding_create_tree(&c->parser_binding, - c->encoding, - nsoption_bool(enable_javascript), - html_process_script, - c); + c->parser = dom_hubbub_parser_create(c->encoding, + true, + nsoption_bool(enable_javascript), + NULL, + html_process_script, + c); - } - - if (error != BINDING_OK) - goto error; - return NSERROR_OK; - -error: - if (error == BINDING_BADENCODING) { - LOG(("Bad encoding: %s", c->encoding ? c->encoding : "")); - msg_data.error = messages_get("ParsingFail"); - nerror = NSERROR_BAD_ENCODING; - } else { - msg_data.error = messages_get("NoMemory"); - nerror = NSERROR_NOMEM; } - content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); + if (c->parser == NULL) { + nsurl_unref(c->base_url); + c->base_url = NULL; - if (c->universal != NULL) { lwc_string_unref(c->universal); c->universal = NULL; - } - if (c->base_url != NULL) { - nsurl_unref(c->base_url); - c->base_url = NULL; + msg_data.error = messages_get("NoMemory"); + content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); + + return NSERROR_NOMEM; } - return nerror; + return NSERROR_OK; + } /** @@ -757,14 +451,16 @@ static bool html_process_data(struct content *c, const char *data, unsigned int size) { html_content *html = (html_content *) c; - binding_error err; + dom_hubbub_error error; const char *encoding; + const char *source_data; + unsigned long source_size; - err = binding_parse_chunk(html->parser_binding, - (const uint8_t *) data, size); - if (err == BINDING_ENCODINGCHANGE) { + error = dom_hubbub_parser_parse_chunk(html->parser, (const uint8_t *) data, size); + + if (error == (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_ENCODINGCHANGE)) { goto encoding_change; - } else if (err != BINDING_OK) { + } else if (error != DOM_HUBBUB_OK) { union content_msg_data msg_data; msg_data.error = messages_get("NoMemory"); @@ -778,9 +474,8 @@ html_process_data(struct content *c, const char *data, unsigned int size) encoding_change: /* Retrieve new encoding */ - encoding = binding_get_encoding( - html->parser_binding, - &html->encoding_source); + encoding = dom_hubbub_parser_get_encoding(html->parser, + &html->encoding_source); if (html->encoding != NULL) talloc_free(html->encoding); @@ -795,16 +490,17 @@ encoding_change: } /* Destroy binding */ - binding_destroy_tree(html->parser_binding); - html->parser_binding = NULL; + dom_hubbub_parser_destroy(html->parser); + html->parser = NULL; /* Create new binding, using the new encoding */ - err = binding_create_tree(&html->parser_binding, - html->encoding, - nsoption_bool(enable_javascript), - html_process_script, - html); - if (err == BINDING_BADENCODING) { + html->parser = dom_hubbub_parser_create(html->encoding, + true, + nsoption_bool(enable_javascript), + NULL, + html_process_script, + html); + if (html->parser == NULL) { /* Ok, we don't support the declared encoding. Bailing out * isn't exactly user-friendly, so fall back to Windows-1252 */ talloc_free(html->encoding); @@ -817,37 +513,35 @@ encoding_change: return false; } - err = binding_create_tree(&html->parser_binding, - html->encoding, - nsoption_bool(enable_javascript), - html_process_script, - html); - } + html->parser = dom_hubbub_parser_create(html->encoding, + true, + nsoption_bool(enable_javascript), + NULL, + html_process_script, + html); - if (err != BINDING_OK) { - union content_msg_data msg_data; + if (html->parser == NULL) { + union content_msg_data msg_data; + + /** @todo add a message callback function and pass the + * parser errors back instead of everything being + * OOM + */ - if (err == BINDING_BADENCODING) { - LOG(("Bad encoding: %s", html->encoding - ? html->encoding : "")); - msg_data.error = messages_get("ParsingFail"); - } else msg_data.error = messages_get("NoMemory"); - content_broadcast(c, CONTENT_MSG_ERROR, msg_data); - return false; - } + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } - { - const char *source_data; - unsigned long source_size; + } - source_data = content__get_source_data(c, &source_size); + source_data = content__get_source_data(c, &source_size); - /* Recurse to reprocess all the data. This is safe because - * the encoding is now specified at parser start which means - * it cannot be changed again. */ - return html_process_data(c, source_data, source_size); - } + /* Recurse to reprocess all the data. This is safe because + * the encoding is now specified at parser start which means + * it cannot be changed again. */ + return html_process_data(c, source_data, source_size); + } @@ -2156,7 +1850,7 @@ static bool html_find_stylesheets(html_content *c, dom_node *html) c->base.active++; LOG(("%d fetches active", c->base.active)); - if (c->quirks == BINDING_QUIRKS_MODE_FULL) { + 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, @@ -2224,7 +1918,7 @@ html_find_stylesheets_no_memory: static bool html_convert(struct content *c) { html_content *htmlc = (html_content *) c; - binding_error err; + dom_hubbub_error err; dom_node *html, *head; union content_msg_data msg_data; unsigned long size; @@ -2235,18 +1929,18 @@ static bool html_convert(struct content *c) /* finish parsing */ content__get_source_data(c, &size); - err = binding_parse_completed(htmlc->parser_binding); - if (err != BINDING_OK) { + err = dom_hubbub_parser_completed(htmlc->parser); + if (err != DOM_HUBBUB_OK) { union content_msg_data msg_data; + /** @todo Improve precessing of errors */ msg_data.error = messages_get("NoMemory"); content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; } - htmlc->document = binding_get_document(htmlc->parser_binding, - &htmlc->quirks); + htmlc->document = dom_hubbub_parser_get_document(htmlc->parser); if (htmlc->document == NULL) { LOG(("Parsing failed")); @@ -2255,10 +1949,18 @@ static bool html_convert(struct content *c) return false; } + exc = dom_document_get_quirks_mode(htmlc->document, &htmlc->quirks); + if (exc != DOM_NO_ERR) { + LOG(("error retrieving quirks")); + } + + LOG(("quirks set to %d", htmlc->quirks)); + + if (htmlc->encoding == NULL) { - const char *encoding = binding_get_encoding( - htmlc->parser_binding, - &htmlc->encoding_source); + const char *encoding; + encoding = dom_hubbub_parser_get_encoding(htmlc->parser, + &htmlc->encoding_source); htmlc->encoding = talloc_strdup(c, encoding); if (htmlc->encoding == NULL) { @@ -2667,13 +2369,14 @@ static void html_destroy(struct content *c) if (html->base_url) nsurl_unref(html->base_url); - if (html->parser_binding != NULL) { - binding_destroy_tree(html->parser_binding); - html->parser_binding = NULL; + if (html->parser != NULL) { + dom_hubbub_parser_destroy(html->parser); + html->parser = NULL; } - if (html->document != NULL) - binding_destroy_document(html->document); + if (html->document != NULL) { + dom_node_unref(html->document); + } /* Free base target */ if (html->base_target != NULL) { @@ -3244,7 +2947,7 @@ const char *html_get_encoding(hlcache_handle *h) * \param h Content to retrieve charset from * \return Pointer to charset, or NULL */ -binding_encoding_source html_get_encoding_source(hlcache_handle *h) +dom_hubbub_encoding_source html_get_encoding_source(hlcache_handle *h) { html_content *c = (html_content *) hlcache_handle_get_content(h); diff --git a/render/html.h b/render/html.h index 5867bcff2..64548f810 100644 --- a/render/html.h +++ b/render/html.h @@ -26,11 +26,14 @@ #define _NETSURF_RENDER_HTML_H_ #include <stdbool.h> + +#include <dom/dom.h> +#include <dom/bindings/hubbub/parser.h> + #include "content/content_type.h" #include "css/css.h" #include "desktop/mouse.h" #include "desktop/plot_style.h" -#include "render/parser_binding.h" #include "desktop/frame_types.h" struct fetch_multipart_data; @@ -167,7 +170,7 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, dom_document *html_get_document(struct hlcache_handle *h); struct box *html_get_box_tree(struct hlcache_handle *h); const char *html_get_encoding(struct hlcache_handle *h); -binding_encoding_source html_get_encoding_source(struct hlcache_handle *h); +dom_hubbub_encoding_source html_get_encoding_source(struct hlcache_handle *h); 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); diff --git a/render/html_internal.h b/render/html_internal.h index d5e1f05f3..ad032f720 100644 --- a/render/html_internal.h +++ b/render/html_internal.h @@ -31,17 +31,17 @@ typedef struct html_content { struct content base; - /** Parser object handle */ - void *parser_binding; + dom_hubbub_parser *parser; /**< Parser object handle */ + /** Document tree */ dom_document *document; /** Quirkyness of document */ - binding_quirks_mode quirks; + dom_document_quirks_mode quirks; /** Encoding of source, NULL if unknown. */ char *encoding; /** Source of encoding information. */ - binding_encoding_source encoding_source; + dom_hubbub_encoding_source encoding_source; /** Base URL (may be a copy of content->url). */ nsurl *base_url; @@ -127,6 +127,12 @@ void html__redraw_a_box(struct content *c, struct box *box); struct browser_window *html_get_browser_window(struct content *c); struct search_context *html_get_search(struct content *c); void html_set_search(struct content *c, struct search_context *s); +/** + * Complete conversion of an HTML document + * + * \param c Content to convert + */ +void html_finish_conversion(html_content *c); /* in render/html_redraw.c */ bool html_redraw(struct content *c, struct content_redraw_data *data, @@ -140,6 +146,10 @@ void html_mouse_action(struct content *c, struct browser_window *bw, void html_overflow_scroll_callback(void *client_data, struct scrollbar_msg_data *scrollbar_data); + +/* in render/html_script.c */ +dom_hubbub_error html_process_script(void *ctx, dom_node *node); + /* in render/html_forms.c */ 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); @@ -163,6 +173,9 @@ extern struct dom_string *html_dom_string_coords; extern struct dom_string *html_dom_string_circle; extern struct dom_string *html_dom_string_poly; extern struct dom_string *html_dom_string_polygon; +extern struct dom_string *html_dom_string_text_javascript; +extern struct dom_string *html_dom_string_type; +extern struct dom_string *html_dom_string_src; #endif diff --git a/render/html_script.c b/render/html_script.c new file mode 100644 index 000000000..631dcca1e --- /dev/null +++ b/render/html_script.c @@ -0,0 +1,339 @@ +/* + * Copyright 2012 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 + * Content for text/html scripts (implementation). + */ + +#include <assert.h> +#include <ctype.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> + +#include "utils/config.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "javascript/js.h" +#include "content/content_protected.h" +#include "content/fetch.h" +#include "render/html_internal.h" + +typedef bool (script_handler_t)(struct jscontext *jscontext, const char *data, size_t size) ; + + +static script_handler_t *select_script_handler(content_type ctype) +{ + if (ctype == CONTENT_JS) { + return js_exec; + } + return NULL; +} + + +/* attempt to progress script execution + * + * execute scripts using algorithm found in: + * http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element + * + */ +static bool html_scripts_exec(html_content *c) +{ + unsigned int i; + struct html_script *s; + script_handler_t *script_handler; + + if (c->jscontext == NULL) + return false; + + for (i = 0, s = c->scripts; i != c->scripts_count; i++, s++) { + if (s->already_started) { + continue; + } + + assert((s->type == HTML_SCRIPT_EXTERNAL) || + (s->type == HTML_SCRIPT_INTERNAL)); + + if (s->type == HTML_SCRIPT_EXTERNAL) { + /* ensure script content is present */ + if (s->data.external == NULL) + continue; + + /* ensure script content fetch status is not an error */ + if (content_get_status(s->data.external) == CONTENT_STATUS_ERROR) + continue; + + /* ensure script handler for content type */ + script_handler = select_script_handler(content_get_type(s->data.external)); + if (script_handler == NULL) + continue; /* unsupported type */ + + if (content_get_status(s->data.external) == CONTENT_STATUS_DONE) { + /* external script is now available */ + const char *data; + unsigned long size; + data = content_get_source_data(s->data.external, &size ); + script_handler(c->jscontext, data, size); + + s->already_started = true; + + } else { + /* script not yet available */ + + /* check if deferable or asynchronous */ + if (!s->defer && !s->async) { + break; + } + } + } + } + + return true; +} + +/* create new html script entry */ +static struct html_script * +html_process_new_script(html_content *c, enum html_script_type type) +{ + struct html_script *nscript; + /* add space for new script entry */ + nscript = realloc(c->scripts, + sizeof(struct html_script) * (c->scripts_count + 1)); + if (nscript == NULL) { + return NULL; + } + + c->scripts = nscript; + + /* increment script entry count */ + nscript = &c->scripts[c->scripts_count]; + c->scripts_count++; + + nscript->already_started = false; + nscript->parser_inserted = false; + nscript->force_async = true; + nscript->ready_exec = false; + nscript->async = false; + nscript->defer = false; + + nscript->type = type; + + return nscript; +} + +/** + * Callback for fetchcache() for linked stylesheets. + */ + +static nserror +html_convert_script_callback(hlcache_handle *script, + const hlcache_event *event, + void *pw) +{ + html_content *parent = pw; + unsigned int i; + struct html_script *s; + + /* Find script */ + for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) { + if (s->type == HTML_SCRIPT_EXTERNAL && + s->data.external == script) + break; + } + + assert(i != parent->scripts_count); + + switch (event->type) { + case CONTENT_MSG_LOADING: + break; + + case CONTENT_MSG_READY: + break; + + case CONTENT_MSG_DONE: + LOG(("script %d done '%s'", i, + nsurl_access(hlcache_handle_get_url(script)))); + parent->base.active--; + LOG(("%d fetches active", parent->base.active)); + + /* script finished loading so try and continue execution */ + html_scripts_exec(parent); + break; + + case CONTENT_MSG_ERROR: + LOG(("script %s failed: %s", + nsurl_access(hlcache_handle_get_url(script)), + event->data.error)); + hlcache_handle_release(script); + s->data.external = NULL; + parent->base.active--; + LOG(("%d fetches active", parent->base.active)); + content_add_error(&parent->base, "?", 0); + + /* script failed loading so try and continue execution */ + html_scripts_exec(parent); + + break; + + case CONTENT_MSG_STATUS: + html_set_status(parent, content_get_status_message(script)); + content_broadcast(&parent->base, CONTENT_MSG_STATUS, + event->data); + break; + + default: + assert(0); + } + + if (parent->base.active == 0) + html_finish_conversion(parent); + + return NSERROR_OK; +} + +/** process script node + * + * + */ +dom_hubbub_error +html_process_script(void *ctx, dom_node *node) +{ + html_content *c = (html_content *)ctx; + dom_exception exc; /* returned by libdom functions */ + dom_string *src, *script, *mimetype; + struct html_script *nscript; + union content_msg_data msg_data; + + /* ensure javascript context is available */ + if (c->jscontext == NULL) { + union content_msg_data msg_data; + + msg_data.jscontext = &c->jscontext; + content_broadcast(&c->base, CONTENT_MSG_GETCTX, msg_data); + LOG(("javascript context %p ", c->jscontext)); + if (c->jscontext == NULL) { + /* no context and it could not be created, abort */ + return DOM_HUBBUB_OK; + } + } + + LOG(("content %p parser %p node %p",c,c->parser, node)); + + exc = dom_element_get_attribute(node, html_dom_string_type, &mimetype); + if (exc != DOM_NO_ERR || mimetype == NULL) { + mimetype = dom_string_ref(html_dom_string_text_javascript); + } + + exc = dom_element_get_attribute(node, html_dom_string_src, &src); + if (exc != DOM_NO_ERR || src == NULL) { + struct lwc_string_s *lwcmimetype; + script_handler_t *script_handler; + + /* does not appear to be a src so script is inline content */ + exc = dom_node_get_text_content(node, &script); + if ((exc != DOM_NO_ERR) || (script == NULL)) { + dom_string_unref(mimetype); + return DOM_HUBBUB_OK; /* no contents, skip */ + } + + nscript = html_process_new_script(c, HTML_STYLESHEET_INTERNAL); + if (nscript == NULL) { + dom_string_unref(mimetype); + dom_string_unref(script); + goto html_process_script_no_memory; + } + + nscript->data.internal = script; + nscript->mimetype = mimetype; + nscript->already_started = true; + + /* charset (encoding) */ + + /* ensure script handler for content type */ + dom_string_intern(mimetype, &lwcmimetype); + script_handler = select_script_handler(content_factory_type_from_mime_type(lwcmimetype)); + lwc_string_unref(lwcmimetype); + + if (script_handler != NULL) { + script_handler(c->jscontext, + dom_string_data(script), + dom_string_byte_length(script)); + } + + + } else { + /* script with a src tag */ + nserror ns_error; + nsurl *joined; + hlcache_child_context child; + + + nscript = html_process_new_script(c, HTML_STYLESHEET_EXTERNAL); + if (nscript == NULL) { + dom_string_unref(src); + dom_string_unref(mimetype); + goto html_process_script_no_memory; + } + + /* charset (encoding) */ + + ns_error = nsurl_join(c->base_url, dom_string_data(src), &joined); + dom_string_unref(src); + if (ns_error != NSERROR_OK) { + dom_string_unref(mimetype); + goto html_process_script_no_memory; + } + + nscript->mimetype = mimetype; /* keep reference to mimetype */ + + LOG(("script %i '%s'", c->scripts_count, nsurl_access(joined))); + + child.charset = c->encoding; + child.quirks = c->base.quirks; + + ns_error = hlcache_handle_retrieve(joined, + 0, + content_get_url(&c->base), + NULL, + html_convert_script_callback, + c, + &child, + CONTENT_SCRIPT, + &nscript->data.external); + + nsurl_unref(joined); + + if (ns_error != NSERROR_OK) { + goto html_process_script_no_memory; + } + + c->base.active++; /* ensure base content knows the fetch is active */ + LOG(("%d fetches active", c->base.active)); + + } + html_scripts_exec(c); + + return DOM_HUBBUB_OK; + +html_process_script_no_memory: + msg_data.error = messages_get("NoMemory"); + content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); + return DOM_HUBBUB_NOMEM; +} diff --git a/render/hubbub_binding.c b/render/hubbub_binding.c deleted file mode 100644 index 2f9899fad..000000000 --- a/render/hubbub_binding.c +++ /dev/null @@ -1,1325 +0,0 @@ -/* - * Copyright 2008 Andrew Sidwell <takkaria@netsurf-browser.org> - * Copyright 2008 John-Mark Bell <jmb@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/>. - */ - -#include <assert.h> -#include <stdbool.h> -#include <string.h> - -#include <libxml/HTMLparser.h> -#include <libxml/HTMLtree.h> - -#include <hubbub/parser.h> -#include <hubbub/tree.h> - -#include "render/form.h" -#include "render/parser_binding.h" - -#include "utils/config.h" -#include "utils/log.h" -#include "utils/talloc.h" -#include "utils/utils.h" - -/** - * Private data attached to each DOM node - */ -typedef struct hubbub_private { - binding_private base; - - uint32_t refcnt; -} hubbub_private; - -typedef struct hubbub_ctx { - hubbub_parser *parser; - - htmlDocPtr document; - bool owns_doc; - - binding_quirks_mode quirks; - - const char *encoding; - binding_encoding_source encoding_source; - -#define NUM_NAMESPACES (6) - xmlNsPtr namespaces[NUM_NAMESPACES]; -#undef NUM_NAMESPACES - - hubbub_tree_handler tree_handler; - - struct form *forms; -} hubbub_ctx; - -static struct { - const char *prefix; - const char *url; -} namespaces[] = { - { NULL, NULL }, - { NULL, "http://www.w3.org/1999/xhtml" }, - { "math", "http://www.w3.org/1998/Math/MathML" }, - { "svg", "http://www.w3.org/2000/svg" }, - { "xlink", "http://www.w3.org/1999/xlink" }, - /** \todo Oh dear. LibXML2 refuses to create any namespace with a - * prefix of "xml". That sucks, royally. */ - { "xml", "http://www.w3.org/XML/1998/namespace" }, - { "xmlns", "http://www.w3.org/2000/xmlns/" } -}; - -static hubbub_private *create_private(uint32_t refcnt); -static hubbub_private *copy_private(const hubbub_private *p, uint32_t refcnt); -static void destroy_private(hubbub_private *p); -static inline char *c_string_from_hubbub_string(hubbub_ctx *ctx, - const hubbub_string *str); -static void create_namespaces(hubbub_ctx *ctx, xmlNode *root); -static hubbub_error create_comment(void *ctx, const hubbub_string *data, - void **result); -static hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, - void **result); -static hubbub_error create_element(void *ctx, const hubbub_tag *tag, - void **result); -static hubbub_error create_text(void *ctx, const hubbub_string *data, - void **result); -static hubbub_error ref_node(void *ctx, void *node); -static hubbub_error unref_node(void *ctx, void *node); -static hubbub_error append_child(void *ctx, void *parent, void *child, - void **result); -static hubbub_error insert_before(void *ctx, void *parent, void *child, - void *ref_child, void **result); -static hubbub_error remove_child(void *ctx, void *parent, void *child, - void **result); -static hubbub_error clone_node(void *ctx, void *node, bool deep, void **result); -static hubbub_error reparent_children(void *ctx, void *node, void *new_parent); -static hubbub_error get_parent(void *ctx, void *node, bool element_only, - void **result); -static hubbub_error has_children(void *ctx, void *node, bool *result); -static hubbub_error form_associate(void *ctx, void *form, void *node); -static hubbub_error add_attributes(void *ctx, void *node, - const hubbub_attribute *attributes, uint32_t n_attributes); -static hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode); -static hubbub_error change_encoding(void *ctx, const char *charset); - -static struct form *parse_form_element(xmlNode *node, const char *docenc); -static struct form_control *parse_input_element(xmlNode *node); -static struct form_control *parse_button_element(xmlNode *node); -static struct form_control *parse_select_element(xmlNode *node); -static struct form_control *parse_textarea_element(xmlNode *node); - -static hubbub_tree_handler tree_handler = { - create_comment, - create_doctype, - create_element, - create_text, - ref_node, - unref_node, - append_child, - insert_before, - remove_child, - clone_node, - reparent_children, - get_parent, - has_children, - form_associate, - add_attributes, - set_quirks_mode, - change_encoding, - NULL -}; - -static void *ns_talloc_based_realloc(void *ptr, size_t len, void *pw) -{ - /* talloc_realloc_size(pw, ptr, 0) == talloc_free(ptr) */ - return talloc_realloc_size(pw, ptr, len); -} - -binding_error binding_create_tree(void *arena, const char *charset, void **ctx) -{ - hubbub_ctx *c; - hubbub_parser_optparams params; - uint32_t i; - hubbub_error error; - - c = malloc(sizeof(hubbub_ctx)); - if (c == NULL) - return BINDING_NOMEM; - - c->parser = NULL; - c->encoding = charset; - c->encoding_source = charset != NULL ? ENCODING_SOURCE_HEADER - : ENCODING_SOURCE_DETECTED; - c->document = NULL; - c->owns_doc = true; - c->quirks = BINDING_QUIRKS_MODE_NONE; - c->forms = NULL; - - error = hubbub_parser_create(charset, true, ns_talloc_based_realloc, - arena, &c->parser); - if (error != HUBBUB_OK) { - free(c); - if (error == HUBBUB_BADENCODING) - return BINDING_BADENCODING; - else - return BINDING_NOMEM; /* Assume OOM */ - } - - c->document = htmlNewDocNoDtD(NULL, NULL); - if (c->document == NULL) { - hubbub_parser_destroy(c->parser); - free(c); - return BINDING_NOMEM; - } - c->document->_private = create_private(0); - if (c->document->_private == NULL) { - xmlFreeDoc(c->document); - hubbub_parser_destroy(c->parser); - free(c); - return BINDING_NOMEM; - } - - for (i = 0; i < sizeof(c->namespaces) / sizeof(c->namespaces[0]); i++) { - c->namespaces[i] = NULL; - } - - c->tree_handler = tree_handler; - c->tree_handler.ctx = (void *) c; - - params.tree_handler = &c->tree_handler; - hubbub_parser_setopt(c->parser, HUBBUB_PARSER_TREE_HANDLER, ¶ms); - - ref_node(c, c->document); - params.document_node = c->document; - hubbub_parser_setopt(c->parser, HUBBUB_PARSER_DOCUMENT_NODE, ¶ms); - - *ctx = (void *) c; - - return BINDING_OK; -} - -binding_error binding_destroy_tree(void *ctx) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - - if (ctx == NULL) - return BINDING_OK; - - if (c->parser != NULL) - hubbub_parser_destroy(c->parser); - - if (c->owns_doc) - binding_destroy_document(c->document); - - c->parser = NULL; - c->encoding = NULL; - c->document = NULL; - - free(c); - - return BINDING_OK; -} - -binding_error binding_parse_chunk(void *ctx, const uint8_t *data, size_t len) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - hubbub_error err; - - err = hubbub_parser_parse_chunk(c->parser, (uint8_t *) data, len); - if (err == HUBBUB_ENCODINGCHANGE) - return BINDING_ENCODINGCHANGE; - - return err == HUBBUB_NOMEM ? BINDING_NOMEM : BINDING_OK; -} - -binding_error binding_parse_completed(void *ctx) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - hubbub_error error; - - error = hubbub_parser_completed(c->parser); - - return error == HUBBUB_NOMEM ? BINDING_NOMEM : BINDING_OK; -} - -const char *binding_get_encoding(void *ctx, binding_encoding_source *source) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - - *source = c->encoding_source; - - return c->encoding != NULL ? c->encoding : "Windows-1252"; -} - -xmlDocPtr binding_get_document(void *ctx, binding_quirks_mode *quirks) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - xmlDocPtr doc = c->document; - - c->owns_doc = false; - - *quirks = c->quirks; - - return doc; -} - -struct form *binding_get_forms(void *ctx) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - - return c->forms; -} - -struct form_control *binding_get_control_for_node(void *ctx, xmlNodePtr node) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - struct form *f; - struct form_control *ctl = NULL; - - for (f = c->forms; f != NULL; f = f->prev) { - for (ctl = f->controls; ctl != NULL; ctl = ctl->next) { - if (ctl->node == node) - return ctl; - } - } - - /* No control found. This implies that it's not associated - * with any form. In this case, we create a control for it - * on the fly. */ - if (strcasecmp((const char *) node->name, "input") == 0) { - ctl = parse_input_element(node); - } else if (strcasecmp((const char *) node->name, "button") == 0) { - ctl = parse_button_element(node); - } else if (strcasecmp((const char *) node->name, "select") == 0) { - ctl = parse_select_element(node); - } else if (strcasecmp((const char *) node->name, "textarea") == 0) { - ctl = parse_textarea_element(node); - } - - return ctl; -} - -void binding_destroy_document(xmlDocPtr doc) -{ - xmlNode *n = (xmlNode *) doc; - - while (n != NULL) { - destroy_private(n->_private); - - if (n->children != NULL) { - n = n->children; - } else if (n->next != NULL) { - n = n->next; - } else { - while (n->parent != NULL && n->parent->next == NULL) - n = n->parent; - - if (n->parent != NULL) - n = n->parent->next; - else - n = NULL; - } - } - - xmlFreeDoc(doc); -} - -/*****************************************************************************/ - -hubbub_private *create_private(uint32_t refcnt) -{ - hubbub_private *pvt = calloc(1, sizeof(*pvt)); - - if (pvt != NULL) - pvt->refcnt = refcnt; - - return pvt; -} - -hubbub_private *copy_private(const hubbub_private *p, uint32_t refcnt) -{ - hubbub_private *pvt = calloc(1, sizeof(*pvt)); - - if (pvt != NULL) { - pvt->refcnt = refcnt; - - if (p->base.nclasses > 0) { - pvt->base.classes = - malloc(p->base.nclasses * sizeof(lwc_string *)); - if (pvt->base.classes == NULL) { - free(pvt); - return NULL; - } - - while (pvt->base.nclasses < p->base.nclasses) { - pvt->base.classes[pvt->base.nclasses] = - lwc_string_ref(p->base.classes[ - pvt->base.nclasses]); - pvt->base.nclasses++; - } - } - - if (p->base.localname != NULL) - pvt->base.localname = lwc_string_ref(p->base.localname); - - if (p->base.id != NULL) - pvt->base.id = lwc_string_ref(p->base.id); - } - - return pvt; -} - -void destroy_private(hubbub_private *p) -{ - if (p->base.localname != NULL) - lwc_string_unref(p->base.localname); - - if (p->base.id != NULL) - lwc_string_unref(p->base.id); - - while (p->base.nclasses > 0) - lwc_string_unref(p->base.classes[--p->base.nclasses]); - - if (p->base.classes != NULL) - free(p->base.classes); - - free(p); -} - -char *c_string_from_hubbub_string(hubbub_ctx *ctx, const hubbub_string *str) -{ - return strndup((const char *) str->ptr, (int) str->len); -} - -void create_namespaces(hubbub_ctx *ctx, xmlNode *root) -{ - uint32_t i; - - for (i = 1; i < sizeof(namespaces) / sizeof(namespaces[0]); i++) { - ctx->namespaces[i - 1] = xmlNewNs(root, - BAD_CAST namespaces[i].url, - BAD_CAST namespaces[i].prefix); - - if (ctx->namespaces[i - 1] == NULL) { - LOG(("Failed creating namespace %s\n", - namespaces[i].prefix)); - } - } -} - -hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - char *content; - xmlNodePtr n; - - content = c_string_from_hubbub_string(c, data); - if (content == NULL) - return HUBBUB_NOMEM; - - n = xmlNewDocComment(c->document, BAD_CAST content); - if (n == NULL) { - free(content); - return HUBBUB_NOMEM; - } - n->_private = create_private(1); - if (n->_private == NULL) { - xmlFreeNode(n); - free(content); - return HUBBUB_NOMEM; - } - - free(content); - - *result = (void *) n; - - return HUBBUB_OK; -} - -hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, - void **result) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - char *name, *public = NULL, *system = NULL; - xmlDtdPtr n; - - name = c_string_from_hubbub_string(c, &doctype->name); - if (name == NULL) - return HUBBUB_NOMEM; - - if (!doctype->public_missing) { - public = c_string_from_hubbub_string(c, &doctype->public_id); - if (public == NULL) { - free(name); - return HUBBUB_NOMEM; - } - } - - if (!doctype->system_missing) { - system = c_string_from_hubbub_string(c, &doctype->system_id); - if (system == NULL) { - free(public); - free(name); - return HUBBUB_NOMEM; - } - } - - n = xmlNewDtd(c->document, BAD_CAST name, - BAD_CAST (public ? public : ""), - BAD_CAST (system ? system : "")); - if (n == NULL) { - free(system); - free(public); - free(name); - return HUBBUB_NOMEM; - } - n->_private = create_private(1); - if (n->_private == NULL) { - xmlFreeDtd(n); - free(system); - free(public); - free(name); - return HUBBUB_NOMEM; - } - - *result = (void *) n; - - free(system); - free(public); - free(name); - - return HUBBUB_OK; -} - -hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - lwc_string *iname; - xmlNodePtr n; - - if (lwc_intern_string((const char *) tag->name.ptr, tag->name.len, - &iname) != lwc_error_ok) { - return HUBBUB_NOMEM; - } - - if (c->namespaces[0] != NULL) { - n = xmlNewDocNode(c->document, c->namespaces[tag->ns - 1], - BAD_CAST lwc_string_data(iname), NULL); - } else { - n = xmlNewDocNode(c->document, NULL, - BAD_CAST lwc_string_data(iname), NULL); - - /* We're creating the root node of the document. Therefore, - * create the namespaces and set this node's namespace */ - if (n != NULL && c->namespaces[0] == NULL) { - create_namespaces(c, (void *) n); - - xmlSetNs(n, c->namespaces[tag->ns - 1]); - } - } - if (n == NULL) { - lwc_string_unref(iname); - return HUBBUB_NOMEM; - } - n->_private = create_private(1); - if (n->_private == NULL) { - xmlFreeNode(n); - lwc_string_unref(iname); - return HUBBUB_NOMEM; - } - - if (tag->n_attributes > 0 && add_attributes(ctx, (void *) n, - tag->attributes, tag->n_attributes) != HUBBUB_OK) { - destroy_private(n->_private); - xmlFreeNode(n); - lwc_string_unref(iname); - return HUBBUB_NOMEM; - } - - if (lwc_string_length(iname) == SLEN("form") && - strcasecmp(lwc_string_data(iname), "form") == 0) { - struct form *form = parse_form_element(n, c->encoding); - - /* Memory exhaustion */ - if (form == NULL) { - destroy_private(n->_private); - xmlFreeNode(n); - lwc_string_unref(iname); - return HUBBUB_NOMEM; - } - - /* Insert into list */ - form->prev = c->forms; - c->forms = form; - } - - ((binding_private *) n->_private)->localname = iname; - - *result = (void *) n; - - return HUBBUB_OK; -} - -hubbub_error create_text(void *ctx, const hubbub_string *data, void **result) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - xmlNodePtr n; - - n = xmlNewDocTextLen(c->document, BAD_CAST data->ptr, (int) data->len); - if (n == NULL) { - return HUBBUB_NOMEM; - } - n->_private = create_private(1); - if (n->_private == NULL) { - xmlFreeNode(n); - return HUBBUB_NOMEM; - } - - *result = (void *) n; - - return HUBBUB_OK; -} - -hubbub_error ref_node(void *ctx, void *node) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - hubbub_private *pvt; - - if (node == c->document) { - xmlDoc *n = (xmlDoc *) node; - pvt = n->_private; - - pvt->refcnt++; - } else { - xmlNode *n = (xmlNode *) node; - pvt = n->_private; - - pvt->refcnt++; - } - - return HUBBUB_OK; -} - -hubbub_error unref_node(void *ctx, void *node) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - hubbub_private *pvt; - - if (node == c->document) { - xmlDoc *n = (xmlDoc *) node; - pvt = n->_private; - - assert(pvt->refcnt != 0 && "Node has refcount of zero"); - - pvt->refcnt--; - } else { - xmlNode *n = (xmlNode *) node; - pvt = n->_private; - - assert(pvt->refcnt != 0 && "Node has refcount of zero"); - - pvt->refcnt--; - - if (pvt->refcnt == 0 && n->parent == NULL) { - destroy_private(pvt); - xmlFreeNode(n); - } - } - - return HUBBUB_OK; -} - -hubbub_error append_child(void *ctx, void *parent, void *child, void **result) -{ - xmlNode *chld = (xmlNode *) child; - xmlNode *p = (xmlNode *) parent; - - /** \todo Text node merging logic as per - * http://www.whatwg.org/specs/web-apps/current-work/multipage/ \ - * tree-construction.html#insert-a-character - * - * Doesn't actually matter for us until we have scripting. Thus, - * this is something which can wait until libdom. - */ - if (chld->type == XML_TEXT_NODE && p->last != NULL && - p->last->type == XML_TEXT_NODE) { - /* Need to clone the child, as libxml will free it if it - * merges the content with a pre-existing text node. */ - chld = xmlCopyNode(chld, 0); - if (chld == NULL) - return HUBBUB_NOMEM; - - *result = xmlAddChild(p, chld); - - assert(*result != (void *) chld); - } else { - *result = xmlAddChild(p, chld); - } - - if (*result == NULL) - return HUBBUB_NOMEM; - - ref_node(ctx, *result); - - return HUBBUB_OK; -} - -hubbub_error insert_before(void *ctx, void *parent, void *child, - void *ref_child, void **result) -{ - xmlNode *chld = (xmlNode *) child; - xmlNode *ref = (xmlNode *) ref_child; - - if (chld->type == XML_TEXT_NODE && ref->prev != NULL && - ref->prev->type == XML_TEXT_NODE) { - /* Clone text node, as it'll be freed by libxml */ - chld = xmlCopyNode(chld, 0); - if (chld == NULL) - return HUBBUB_NOMEM; - - *result = xmlAddNextSibling(ref->prev, chld); - - assert(*result != (void *) chld); - } else { - *result = xmlAddPrevSibling(ref, chld); - } - - if (*result == NULL) - return HUBBUB_NOMEM; - - ref_node(ctx, *result); - - return HUBBUB_OK; -} - -hubbub_error remove_child(void *ctx, void *parent, void *child, void **result) -{ - xmlNode *chld = (xmlNode *) child; - - xmlUnlinkNode(chld); - - *result = child; - - ref_node(ctx, *result); - - return HUBBUB_OK; -} - -hubbub_error clone_node(void *ctx, void *node, bool deep, void **result) -{ - xmlNode *n = (xmlNode *) node; - xmlNode *clonedtree; - - /* Shallow clone node */ - clonedtree = xmlCopyNode(n, 2); - if (clonedtree == NULL) - return HUBBUB_NOMEM; - - clonedtree->_private = copy_private(n->_private, 1); - if (clonedtree->_private == NULL) { - xmlFreeNode(clonedtree); - return HUBBUB_NOMEM; - } - - /* Iteratively clone children too, if required */ - if (deep && n->children != NULL) { - xmlNode *parent = clonedtree, *copy; - - n = n->children; - - while (n != node) { - copy = xmlCopyNode(n, 2); - if (copy == NULL) - goto error; - - copy->_private = copy_private(n->_private, 0); - if (copy->_private == NULL) { - xmlFreeNode(copy); - goto error; - } - - xmlAddChild(parent, copy); - - if (n->children != NULL) { - parent = copy; - n = n->children; - } else if (n->next != NULL) { - n = n->next; - } else { - while (n->parent != node && - n->parent->next == NULL) { - parent = parent->parent; - n = n->parent; - } - - if (n->parent != node) { - parent = parent->parent; - n = n->parent->next; - } else - n = node; - } - } - } - - *result = clonedtree; - - return HUBBUB_OK; - -error: - n = clonedtree; - - while (n != NULL) { - destroy_private(n->_private); - - if (n->children != NULL) { - n = n->children; - } else if (n->next != NULL) { - n = n->next; - } else { - while (n->parent != NULL && n->parent->next == NULL) { - n = n->parent; - } - - if (n->parent != NULL) - n = n->parent->next; - else - n = NULL; - } - } - - xmlFreeNode(clonedtree); - - return HUBBUB_NOMEM; -} - -hubbub_error reparent_children(void *ctx, void *node, void *new_parent) -{ - xmlNode *n = (xmlNode *) node; - xmlNode *p = (xmlNode *) new_parent; - xmlNode *child; - - for (child = n->children; child != NULL; ) { - xmlNode *next = child->next; - - xmlUnlinkNode(child); - - if (xmlAddChild(p, child) == NULL) - return HUBBUB_NOMEM; - - child = next; - } - - return HUBBUB_OK; -} - -hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result) -{ - xmlNode *n = (xmlNode *) node; - - *result = (void *) n->parent; - - if (*result != NULL && element_only && - ((xmlNode *) *result)->type != XML_ELEMENT_NODE) { - *result = NULL; - } - - if (*result != NULL) - ref_node(ctx, *result); - - return HUBBUB_OK; -} - -hubbub_error has_children(void *ctx, void *node, bool *result) -{ - xmlNode *n = (xmlNode *) node; - - *result = n->children != NULL; - - return HUBBUB_OK; -} - -hubbub_error form_associate(void *ctx, void *form, void *node) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - xmlNode *n = (xmlNode *) node; - struct form *f; - struct form_control *control = NULL; - xmlChar *id = NULL; - - /* Find form object to associate with: - * - * 1) If node possesses an @form, use the form with a matching @id - * 2) Otherwise, use the form provided - */ - id = xmlGetProp(n, (const xmlChar *) "form"); - for (f = c->forms; f != NULL; f = f->prev) { - if (id == NULL && f->node == form) { - break; - } else if (id != NULL) { - xmlNode *fn = (xmlNode *) f->node; - xmlChar *fid = xmlGetProp(fn, (const xmlChar *) "id"); - - if (fid != NULL && strcmp((char *) id, - (char *) fid) == 0) { - xmlFree(fid); - break; - } else if (fid != NULL) { - xmlFree(fid); - } - } - } - if (id != NULL) - xmlFree(id); - - /* None found -- give up */ - if (f == NULL) - return HUBBUB_OK; - - /* Will be one of: button, fieldset, input, label, - * output, select, textarea. - * - * We ignore fieldset, label and output. - */ - if (strcasecmp((const char *) n->name, "input") == 0) { - control = parse_input_element(n); - } else if (strcasecmp((const char *) n->name, "button") == 0) { - control = parse_button_element(n); - } else if (strcasecmp((const char *) n->name, "select") == 0) { - control = parse_select_element(n); - } else if (strcasecmp((const char *) n->name, "textarea") == 0) { - control = parse_textarea_element(n); - } else - return HUBBUB_OK; - - /* Memory exhaustion */ - if (control == NULL) - return HUBBUB_NOMEM; - - /* Add the control to the form */ - form_add_control(f, control); - - return HUBBUB_OK; -} - -static hubbub_error parse_class_attr(lwc_string *value, - lwc_string ***classes, uint32_t *nclasses) -{ - const char *pv; - lwc_string **cls = NULL; - uint32_t count = 0; - - /* Count number of classes */ - for (pv = lwc_string_data(value); *pv != '\0'; ) { - if (*pv != ' ') { - while (*pv != ' ' && *pv != '\0') - pv++; - count++; - } else { - while (*pv == ' ') - pv++; - } - } - - /* If there are some, unpack them */ - if (count > 0) { - cls = malloc(count * sizeof(lwc_string *)); - if (cls == NULL) - return HUBBUB_NOMEM; - - for (pv = lwc_string_data(value), count = 0; *pv != '\0'; ) { - if (*pv != ' ') { - const char *s = pv; - while (*pv != ' ' && *pv != '\0') - pv++; - if (lwc_intern_string(s, pv - s, - &cls[count]) != lwc_error_ok) - goto error; - count++; - } else { - while (*pv == ' ') - pv++; - } - } - } - - *classes = cls; - *nclasses = count; - - return HUBBUB_OK; -error: - while (count > 0) - lwc_string_unref(cls[--count]); - - free(cls); - - return HUBBUB_NOMEM; -} - -hubbub_error add_attributes(void *ctx, void *node, - const hubbub_attribute *attributes, uint32_t n_attributes) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - xmlNode *n = (xmlNode *) node; - binding_private *p = n->_private; - uint32_t attr; - - for (attr = 0; attr < n_attributes; attr++) { - xmlAttr *prop; - lwc_string *name, *value; - - if (lwc_intern_string((const char *) attributes[attr].name.ptr, - attributes[attr].name.len, - &name) != lwc_error_ok) - return HUBBUB_NOMEM; - - if (lwc_intern_string((const char *) attributes[attr].value.ptr, - attributes[attr].value.len, - &value) != lwc_error_ok) { - lwc_string_unref(name); - return HUBBUB_NOMEM; - } - - if (attributes[attr].ns != HUBBUB_NS_NULL && - c->namespaces[0] != NULL) { - prop = xmlNewNsProp(n, - c->namespaces[attributes[attr].ns - 1], - BAD_CAST lwc_string_data(name), - BAD_CAST lwc_string_data(value)); - } else { - prop = xmlNewProp(n, BAD_CAST lwc_string_data(name), - BAD_CAST lwc_string_data(value)); - } - - /* Handle @id / @class */ - if (p->id == NULL && lwc_string_length(name) == SLEN("id") && - strcasecmp(lwc_string_data(name), "id") == 0) { - p->id = lwc_string_ref(value); - } else if (p->nclasses == 0 && - lwc_string_length(name) == SLEN("class") && - strcasecmp(lwc_string_data(name), - "class") == 0) { - hubbub_error error; - - error = parse_class_attr(value, &p->classes, - &p->nclasses); - if (error != HUBBUB_OK) { - lwc_string_unref(value); - lwc_string_unref(name); - return error; - } - } - - lwc_string_unref(value); - lwc_string_unref(name); - - if (prop == NULL) { - return HUBBUB_NOMEM; - } - } - - return HUBBUB_OK; -} - -hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - - switch (mode) { - case HUBBUB_QUIRKS_MODE_NONE: - c->quirks = BINDING_QUIRKS_MODE_NONE; - break; - case HUBBUB_QUIRKS_MODE_LIMITED: - c->quirks = BINDING_QUIRKS_MODE_LIMITED; - break; - case HUBBUB_QUIRKS_MODE_FULL: - c->quirks = BINDING_QUIRKS_MODE_FULL; - break; - } - - return HUBBUB_OK; -} - -hubbub_error change_encoding(void *ctx, const char *charset) -{ - hubbub_ctx *c = (hubbub_ctx *) ctx; - uint32_t source; - const char *name; - - /* If we have an encoding here, it means we are *certain* */ - if (c->encoding != NULL) { - return HUBBUB_OK; - } - - /* Find the confidence otherwise (can only be from a BOM) */ - name = hubbub_parser_read_charset(c->parser, &source); - - if (source == HUBBUB_CHARSET_CONFIDENT) { - c->encoding_source = ENCODING_SOURCE_DETECTED; - c->encoding = (char *) charset; - return HUBBUB_OK; - } - - /* So here we have something of confidence tentative... */ - /* http://www.whatwg.org/specs/web-apps/current-work/#change */ - - /* 2. "If the new encoding is identical or equivalent to the encoding - * that is already being used to interpret the input stream, then set - * the confidence to confident and abort these steps." */ - - /* Whatever happens, the encoding should be set here; either for - * reprocessing with a different charset, or for confirming that the - * charset is in fact correct */ - c->encoding = charset; - c->encoding_source = ENCODING_SOURCE_META; - - /* Equal encodings will have the same string pointers */ - return (charset == name) ? HUBBUB_OK : HUBBUB_ENCODINGCHANGE; -} - -struct form *parse_form_element(xmlNode *node, const char *docenc) -{ - struct form *form; - form_method method; - xmlChar *action, *meth, *charset, *target; - - action = xmlGetProp(node, (const xmlChar *) "action"); - charset = xmlGetProp(node, (const xmlChar *) "accept-charset"); - target = xmlGetProp(node, (const xmlChar *) "target"); - - method = method_GET; - meth = xmlGetProp(node, (const xmlChar *) "method"); - if (meth != NULL) { - if (strcasecmp((char *) meth, "post") == 0) { - xmlChar *enctype; - - method = method_POST_URLENC; - - enctype = xmlGetProp(node, (const xmlChar *) "enctype"); - if (enctype != NULL) { - if (strcasecmp((char *) enctype, - "multipart/form-data") == 0) - method = method_POST_MULTIPART; - - xmlFree(enctype); - } - } - xmlFree(meth); - } - - form = form_new(node, (char *) action, (char *) target, method, - (char *) charset, docenc); - - if (target != NULL) - xmlFree(target); - if (charset != NULL) - xmlFree(charset); - if (action != NULL) - xmlFree(action); - - return form; -} - -struct form_control *parse_input_element(xmlNode *node) -{ - struct form_control *control = NULL; - xmlChar *type = xmlGetProp(node, (const xmlChar *) "type"); - xmlChar *name; - - if (type != NULL && strcasecmp((char *) type, "password") == 0) { - control = form_new_control(node, GADGET_PASSWORD); - } else if (type != NULL && strcasecmp((char *) type, "file") == 0) { - control = form_new_control(node, GADGET_FILE); - } else if (type != NULL && strcasecmp((char *) type, "hidden") == 0) { - control = form_new_control(node, GADGET_HIDDEN); - } else if (type != NULL && strcasecmp((char *) type, "checkbox") == 0) { - control = form_new_control(node, GADGET_CHECKBOX); - } else if (type != NULL && strcasecmp((char *) type, "radio") == 0) { - control = form_new_control(node, GADGET_RADIO); - } else if (type != NULL && strcasecmp((char *) type, "submit") == 0) { - control = form_new_control(node, GADGET_SUBMIT); - } else if (type != NULL && strcasecmp((char *) type, "reset") == 0) { - control = form_new_control(node, GADGET_RESET); - } else if (type != NULL && strcasecmp((char *) type, "button") == 0) { - control = form_new_control(node, GADGET_BUTTON); - } else if (type != NULL && strcasecmp((char *) type, "image") == 0) { - control = form_new_control(node, GADGET_IMAGE); - } else { - control = form_new_control(node, GADGET_TEXTBOX); - } - - xmlFree(type); - - if (control == NULL) - return NULL; - - if (control->type == GADGET_CHECKBOX || control->type == GADGET_RADIO) { - control->selected = - xmlHasProp(node, (const xmlChar *) "checked") != NULL; - } - - if (control->type == GADGET_PASSWORD || - control->type == GADGET_TEXTBOX) { - xmlChar *len = xmlGetProp(node, (const xmlChar *) "maxlength"); - if (len != NULL) { - if (len[0] != '\0') - control->maxlength = atoi((char *) len); - xmlFree(len); - } - } - - if (control->type != GADGET_FILE && control->type != GADGET_IMAGE) { - xmlChar *value = xmlGetProp(node, (const xmlChar *) "value"); - if (value != NULL) { - control->value = strdup((char *) value); - - xmlFree(value); - - if (control->value == NULL) { - form_free_control(control); - return NULL; - } - - control->length = strlen(control->value); - } - - if (control->type == GADGET_TEXTBOX || - control->type == GADGET_PASSWORD) { - if (control->value == NULL) { - control->value = strdup(""); - if (control->value == NULL) { - form_free_control(control); - return NULL; - } - - control->length = 0; - } - - control->initial_value = strdup(control->value); - if (control->initial_value == NULL) { - form_free_control(control); - return NULL; - } - } - } - - name = xmlGetProp(node, (const xmlChar *) "name"); - if (name != NULL) { - control->name = strdup((char *) name); - - xmlFree(name); - - if (control->name == NULL) { - form_free_control(control); - return NULL; - } - } - - return control; -} - -struct form_control *parse_button_element(xmlNode *node) -{ - struct form_control *control; - xmlChar *type = xmlGetProp(node, (const xmlChar *) "type"); - xmlChar *name; - xmlChar *value; - - if (type == NULL || strcasecmp((char *) type, "submit") == 0) { - control = form_new_control(node, GADGET_SUBMIT); - } else if (strcasecmp((char *) type, "reset") == 0) { - control = form_new_control(node, GADGET_RESET); - } else { - control = form_new_control(node, GADGET_BUTTON); - } - - xmlFree(type); - - if (control == NULL) - return NULL; - - value = xmlGetProp(node, (const xmlChar *) "value"); - if (value != NULL) { - control->value = strdup((char *) value); - - xmlFree(value); - - if (control->value == NULL) { - form_free_control(control); - return NULL; - } - } - - name = xmlGetProp(node, (const xmlChar *) "name"); - if (name != NULL) { - control->name = strdup((char *) name); - - xmlFree(name); - - if (control->name == NULL) { - form_free_control(control); - return NULL; - } - } - - return control; -} - -struct form_control *parse_select_element(xmlNode *node) -{ - struct form_control *control = form_new_control(node, GADGET_SELECT); - xmlChar *name; - - if (control == NULL) - return NULL; - - control->data.select.multiple = - xmlHasProp(node, (const xmlChar *) "multiple") != NULL; - - name = xmlGetProp(node, (const xmlChar *) "name"); - if (name != NULL) { - control->name = strdup((char *) name); - - xmlFree(name); - - if (control->name == NULL) { - form_free_control(control); - return NULL; - } - } - - return control; -} - -struct form_control *parse_textarea_element(xmlNode *node) -{ - struct form_control *control = form_new_control(node, GADGET_TEXTAREA); - xmlChar *name; - - if (control == NULL) - return NULL; - - name = xmlGetProp(node, (const xmlChar *) "name"); - if (name != NULL) { - control->name = strdup((char *) name); - - xmlFree(name); - - if (control->name == NULL) { - form_free_control(control); - return NULL; - } - } - - return control; -} - diff --git a/render/libdom_binding.c b/render/libdom_binding.c deleted file mode 100644 index 9ae76469c..000000000 --- a/render/libdom_binding.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2011 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/>. - */ - -#include <dom/dom.h> -#include <dom/bindings/hubbub/parser.h> - -#include "render/form.h" -#include "render/parser_binding.h" - -#include "utils/log.h" - -binding_error binding_create_tree(void **ctx, const char *charset, bool enable_script, dom_script script, void *context) -{ - dom_hubbub_parser *parser = NULL; - - parser = dom_hubbub_parser_create(charset, true, enable_script, NULL, script, context); - if (parser == NULL) { - LOG(("Can't create Hubbub Parser\n")); - return BINDING_NOMEM; - } - *ctx = parser; - return BINDING_OK; -} - -binding_error binding_destroy_tree(void *ctx) -{ - dom_hubbub_parser_destroy(ctx); - return BINDING_OK; -} - -binding_error binding_parse_chunk(void *ctx, const uint8_t *data, size_t len) -{ - dom_hubbub_error error; - error = dom_hubbub_parser_parse_chunk(ctx, data, len); - if (error == (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_ENCODINGCHANGE)) { - return BINDING_ENCODINGCHANGE; - } else if (error != DOM_HUBBUB_OK) { - return BINDING_NOMEM; - } - return BINDING_OK; -} - -binding_error binding_parse_completed(void *ctx) -{ - dom_hubbub_error error; - error = dom_hubbub_parser_completed(ctx); - if (error != DOM_HUBBUB_OK) { - return BINDING_NOMEM; - } - return BINDING_OK; -} - -const char *binding_get_encoding(void *ctx, binding_encoding_source *source) -{ - dom_hubbub_encoding_source hubbub_src; - const char *encoding; - - encoding = dom_hubbub_parser_get_encoding(ctx, &hubbub_src); - - switch (hubbub_src) { - case DOM_HUBBUB_ENCODING_SOURCE_HEADER: - *source = ENCODING_SOURCE_HEADER; - break; - - case DOM_HUBBUB_ENCODING_SOURCE_DETECTED: - *source = ENCODING_SOURCE_DETECTED; - break; - - case DOM_HUBBUB_ENCODING_SOURCE_META: - *source = ENCODING_SOURCE_META; - break; - } - - return encoding; -} - -dom_document *binding_get_document(void *ctx, binding_quirks_mode *quirks) -{ - return dom_hubbub_parser_get_document(ctx); -} - -struct form *binding_get_forms(void *ctx) -{ - return NULL; -} - -struct form_control *binding_get_control_for_node(void *ctx, dom_node *node) -{ - /** \todo implement properly */ - struct form_control *ctl = form_new_control(node, GADGET_HIDDEN); - if (ctl != NULL) { - ctl->value = strdup(""); - ctl->initial_value = strdup(""); - ctl->name = strdup("foo"); - - if (ctl->value == NULL || ctl->initial_value == NULL || - ctl->name == NULL) { - form_free_control(ctl); - ctl = NULL; - } - } - - return ctl; -} - -void binding_destroy_document(dom_document *doc) -{ - dom_node_unref(doc); -} - - diff --git a/render/parser_binding.h b/render/parser_binding.h deleted file mode 100644 index cf3497867..000000000 --- a/render/parser_binding.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2008 John-Mark Bell <jmb@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/>. - */ - -#ifndef _NETSURF_RENDER_PARSER_BINDING_H_ -#define _NETSURF_RENDER_PARSER_BINDING_H_ - -#include <dom/dom.h> -#include <dom/bindings/hubbub/parser.h> - -struct box; -struct form; -struct form_control; - -typedef enum binding_error { - BINDING_OK, - BINDING_NOMEM, - BINDING_BADENCODING, - BINDING_ENCODINGCHANGE -} binding_error; - -typedef enum binding_encoding_source { - ENCODING_SOURCE_HEADER, - ENCODING_SOURCE_DETECTED, - ENCODING_SOURCE_META -} binding_encoding_source; - -typedef enum binding_quirks_mode { - BINDING_QUIRKS_MODE_NONE, - BINDING_QUIRKS_MODE_LIMITED, - BINDING_QUIRKS_MODE_FULL -} binding_quirks_mode; - -binding_error binding_create_tree(void **ctx, const char *charset, bool enable_script, dom_script script, void *context); -binding_error binding_destroy_tree(void *ctx); - -binding_error binding_parse_chunk(void *ctx, const uint8_t *data, size_t len); -binding_error binding_parse_completed(void *ctx); - -const char *binding_get_encoding(void *ctx, binding_encoding_source *source); -dom_document *binding_get_document(void *ctx, binding_quirks_mode *quirks); - -struct form *binding_get_forms(void *ctx); -struct form_control *binding_get_control_for_node(void *ctx, dom_node *node); - -void binding_destroy_document(dom_document *doc); - -#endif - |