summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2012-07-13 13:19:04 -0600
committerVincent Sanders <vince@netsurf-browser.org>2012-07-13 17:37:21 -0600
commit019be7616caf377f5b233c98206bc0c5d45a9793 (patch)
tree5576e28f2ac9ff647532f25ac6d33850cf446060
parentf2aa118025ac1623947ce6d04840554e518759bd (diff)
downloadnetsurf-019be7616caf377f5b233c98206bc0c5d45a9793.tar.gz
netsurf-019be7616caf377f5b233c98206bc0c5d45a9793.tar.bz2
split out script handling from html
-rw-r--r--Makefile.sources3
-rw-r--r--render/html.c309
-rw-r--r--render/html_internal.h12
-rw-r--r--render/html_script.c339
4 files changed, 357 insertions, 306 deletions
diff --git a/Makefile.sources b/Makefile.sources
index 3dcec40a3..f76ba0904 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -12,7 +12,8 @@ S_FETCHERS := curl.c data.c file.c about.c resource.c
S_CSS := css.c dump.c internal.c select.c utils.c
S_RENDER := box.c box_construct.c box_normalise.c \
- font.c form.c html.c html_interaction.c html_redraw.c \
+ font.c form.c \
+ html.c html_script.c html_interaction.c html_redraw.c \
libdom_binding.c imagemap.c layout.c list.c search.c table.c \
textinput.c textplain.c
diff --git a/render/html.c b/render/html.c
index 495cd7dab..bb6748a73 100644
--- a/render/html.c
+++ b/render/html.c
@@ -38,7 +38,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 +85,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 +116,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)
{
@@ -309,7 +207,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,205 +298,6 @@ 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)
diff --git a/render/html_internal.h b/render/html_internal.h
index da3d686bd..acd7a2cdc 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -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,9 @@ 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);
+
/* Useful dom_string pointers */
struct dom_string;
@@ -159,6 +168,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..f925cfedf
--- /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_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;
+}