summaryrefslogtreecommitdiff
path: root/render/html_script.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2018-05-10 11:34:26 +0100
committerVincent Sanders <vince@kyllikki.org>2018-05-10 13:37:02 +0100
commit2a03ea30490892ac52b3da325ab78e1aa888f83e (patch)
treed041e4a2aab3b224ad41612d47ea2119895e27ac /render/html_script.c
parent1b892391d7859398c212b9fda5b532308fa6e8fd (diff)
downloadnetsurf-2a03ea30490892ac52b3da325ab78e1aa888f83e.tar.gz
netsurf-2a03ea30490892ac52b3da325ab78e1aa888f83e.tar.bz2
move html and text content handlers where they belong
Diffstat (limited to 'render/html_script.c')
-rw-r--r--render/html_script.c603
1 files changed, 0 insertions, 603 deletions
diff --git a/render/html_script.c b/render/html_script.c
deleted file mode 100644
index c73a4806d..000000000
--- a/render/html_script.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * 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/corestrings.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "netsurf/content.h"
-#include "javascript/js.h"
-#include "content/content_protected.h"
-#include "content/fetch.h"
-#include "content/hlcache.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;
-}
-
-
-/* exported internal interface documented in render/html_internal.h */
-nserror html_script_exec(html_content *c)
-{
- unsigned int i;
- struct html_script *s;
- script_handler_t *script_handler;
-
- if (c->jscontext == NULL) {
- return NSERROR_BAD_PARAMETER;
- }
-
- for (i = 0, s = c->scripts; i != c->scripts_count; i++, s++) {
- if (s->already_started) {
- continue;
- }
-
- if ((s->type == HTML_SCRIPT_ASYNC) ||
- (s->type == HTML_SCRIPT_DEFER)) {
- /* ensure script content is present */
- if (s->data.handle == NULL)
- continue;
-
- /* ensure script content fetch status is not an error */
- if (content_get_status(s->data.handle) ==
- CONTENT_STATUS_ERROR)
- continue;
-
- /* ensure script handler for content type */
- script_handler = select_script_handler(
- content_get_type(s->data.handle));
- if (script_handler == NULL)
- continue; /* unsupported type */
-
- if (content_get_status(s->data.handle) ==
- CONTENT_STATUS_DONE) {
- /* external script is now available */
- const char *data;
- unsigned long size;
- data = content_get_source_data(
- s->data.handle, &size );
- script_handler(c->jscontext, data, size);
-
- s->already_started = true;
-
- }
- }
- }
-
- return NSERROR_OK;
-}
-
-/* create new html script entry */
-static struct html_script *
-html_process_new_script(html_content *c,
- dom_string *mimetype,
- 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;
-
- nscript->mimetype = dom_string_ref(mimetype); /* reference mimetype */
-
- return nscript;
-}
-
-/**
- * Callback for asyncronous scripts
- */
-static nserror
-convert_script_async_cb(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_ASYNC && s->data.handle == script)
- break;
- }
-
- assert(i != parent->scripts_count);
-
- switch (event->type) {
- case CONTENT_MSG_LOADING:
- break;
-
- case CONTENT_MSG_READY:
- break;
-
- case CONTENT_MSG_DONE:
- NSLOG(netsurf, INFO, "script %d done '%s'", i,
- nsurl_access(hlcache_handle_get_url(script)));
- parent->base.active--;
- NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
-
- break;
-
- case CONTENT_MSG_ERROR:
- NSLOG(netsurf, INFO, "script %s failed: %s",
- nsurl_access(hlcache_handle_get_url(script)),
- event->data.error);
- /* fall through */
-
- case CONTENT_MSG_ERRORCODE:
- hlcache_handle_release(script);
- s->data.handle = NULL;
- parent->base.active--;
- NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
- content_add_error(&parent->base, "?", 0);
-
- break;
-
- default:
- break;
- }
-
- /* if there are no active fetches remaining begin post parse
- * conversion
- */
- if (html_can_begin_conversion(parent)) {
- html_begin_conversion(parent);
- }
-
- return NSERROR_OK;
-}
-
-/**
- * Callback for defer scripts
- */
-static nserror
-convert_script_defer_cb(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_DEFER && s->data.handle == script)
- break;
- }
-
- assert(i != parent->scripts_count);
-
- switch (event->type) {
-
- case CONTENT_MSG_DONE:
- NSLOG(netsurf, INFO, "script %d done '%s'", i,
- nsurl_access(hlcache_handle_get_url(script)));
- parent->base.active--;
- NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
-
- break;
-
- case CONTENT_MSG_ERROR:
- NSLOG(netsurf, INFO, "script %s failed: %s",
- nsurl_access(hlcache_handle_get_url(script)),
- event->data.error);
- /* fall through */
-
- case CONTENT_MSG_ERRORCODE:
- hlcache_handle_release(script);
- s->data.handle = NULL;
- parent->base.active--;
- NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
- content_add_error(&parent->base, "?", 0);
-
- break;
-
- default:
- break;
- }
-
- /* if there are no active fetches remaining begin post parse
- * conversion
- */
- if (html_can_begin_conversion(parent)) {
- html_begin_conversion(parent);
- }
-
- return NSERROR_OK;
-}
-
-/**
- * Callback for syncronous scripts
- */
-static nserror
-convert_script_sync_cb(hlcache_handle *script,
- const hlcache_event *event,
- void *pw)
-{
- html_content *parent = pw;
- unsigned int i;
- struct html_script *s;
- script_handler_t *script_handler;
- dom_hubbub_error err;
-
- /* Find script */
- for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) {
- if (s->type == HTML_SCRIPT_SYNC && s->data.handle == script)
- break;
- }
-
- assert(i != parent->scripts_count);
-
- switch (event->type) {
- case CONTENT_MSG_DONE:
- NSLOG(netsurf, INFO, "script %d done '%s'", i,
- nsurl_access(hlcache_handle_get_url(script)));
- parent->base.active--;
- NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
-
- s->already_started = true;
-
- /* attempt to execute script */
- script_handler = select_script_handler(content_get_type(s->data.handle));
- if (script_handler != NULL && parent->jscontext != NULL) {
- /* script has a handler */
- const char *data;
- unsigned long size;
- data = content_get_source_data(s->data.handle, &size );
- script_handler(parent->jscontext, data, size);
- }
-
- /* continue parse */
- err = dom_hubbub_parser_pause(parent->parser, false);
- if (err != DOM_HUBBUB_OK) {
- NSLOG(netsurf, INFO, "unpause returned 0x%x", err);
- }
-
- break;
-
- case CONTENT_MSG_ERROR:
- NSLOG(netsurf, INFO, "script %s failed: %s",
- nsurl_access(hlcache_handle_get_url(script)),
- event->data.error);
- /* fall through */
-
- case CONTENT_MSG_ERRORCODE:
- hlcache_handle_release(script);
- s->data.handle = NULL;
- parent->base.active--;
-
- NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
- content_add_error(&parent->base, "?", 0);
-
- s->already_started = true;
-
- /* continue parse */
- err = dom_hubbub_parser_pause(parent->parser, false);
- if (err != DOM_HUBBUB_OK) {
- NSLOG(netsurf, INFO, "unpause returned 0x%x", err);
- }
-
- break;
-
- default:
- break;
- }
-
- /* if there are no active fetches remaining begin post parse
- * conversion
- */
- if (html_can_begin_conversion(parent)) {
- html_begin_conversion(parent);
- }
-
- return NSERROR_OK;
-}
-
-/**
- * process a script with a src tag
- */
-static dom_hubbub_error
-exec_src_script(html_content *c,
- dom_node *node,
- dom_string *mimetype,
- dom_string *src)
-{
- nserror ns_error;
- nsurl *joined;
- hlcache_child_context child;
- struct html_script *nscript;
- bool async;
- bool defer;
- enum html_script_type script_type;
- hlcache_handle_callback script_cb;
- dom_hubbub_error ret = DOM_HUBBUB_OK;
- dom_exception exc; /* returned by libdom functions */
-
- /* src url */
- ns_error = nsurl_join(c->base_url, dom_string_data(src), &joined);
- if (ns_error != NSERROR_OK) {
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
- return DOM_HUBBUB_NOMEM;
- }
-
- NSLOG(netsurf, INFO, "script %i '%s'", c->scripts_count,
- nsurl_access(joined));
-
- /* there are three ways to process the script tag at this point:
- *
- * Syncronously pause the parent parse and continue after
- * the script has downloaded and executed. (default)
- * Async Start the script downloading and execute it when it
- * becomes available.
- * Defered Start the script downloading and execute it when
- * the page has completed parsing, may be set along
- * with async where it is ignored.
- */
-
- /* we interpret the presence of the async and defer attribute
- * as true and ignore its value, technically only the empty
- * value or the attribute name itself are valid. However
- * various browsers interpret this in various ways the most
- * compatible approach is to be liberal and accept any
- * value. Note setting the values to "false" still makes them true!
- */
- exc = dom_element_has_attribute(node, corestring_dom_async, &async);
- if (exc != DOM_NO_ERR) {
- return DOM_HUBBUB_OK; /* dom error */
- }
-
- if (async) {
- /* asyncronous script */
- script_type = HTML_SCRIPT_ASYNC;
- script_cb = convert_script_async_cb;
-
- } else {
- exc = dom_element_has_attribute(node,
- corestring_dom_defer, &defer);
- if (exc != DOM_NO_ERR) {
- return DOM_HUBBUB_OK; /* dom error */
- }
-
- if (defer) {
- /* defered script */
- script_type = HTML_SCRIPT_DEFER;
- script_cb = convert_script_defer_cb;
- } else {
- /* syncronous script */
- script_type = HTML_SCRIPT_SYNC;
- script_cb = convert_script_sync_cb;
- }
- }
-
- nscript = html_process_new_script(c, mimetype, script_type);
- if (nscript == NULL) {
- nsurl_unref(joined);
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
- return DOM_HUBBUB_NOMEM;
- }
-
- /* set up child fetch encoding and quirks */
- child.charset = c->encoding;
- child.quirks = c->base.quirks;
-
- ns_error = hlcache_handle_retrieve(joined,
- 0,
- content_get_url(&c->base),
- NULL,
- script_cb,
- c,
- &child,
- CONTENT_SCRIPT,
- &nscript->data.handle);
-
-
- nsurl_unref(joined);
-
- if (ns_error != NSERROR_OK) {
- /* @todo Deal with fetch error better. currently assume
- * fetch never became active
- */
- /* mark duff script fetch as already started */
- nscript->already_started = true;
- NSLOG(netsurf, INFO, "Fetch failed with error %d", ns_error);
- } else {
- /* update base content active fetch count */
- c->base.active++;
- NSLOG(netsurf, INFO, "%d fetches active", c->base.active);
-
- switch (script_type) {
- case HTML_SCRIPT_SYNC:
- ret = DOM_HUBBUB_HUBBUB_ERR | HUBBUB_PAUSED;
-
- case HTML_SCRIPT_ASYNC:
- break;
-
- case HTML_SCRIPT_DEFER:
- break;
-
- default:
- assert(0);
- }
- }
-
- return ret;
-}
-
-static dom_hubbub_error
-exec_inline_script(html_content *c, dom_node *node, dom_string *mimetype)
-{
- dom_string *script;
- dom_exception exc; /* returned by libdom functions */
- struct lwc_string_s *lwcmimetype;
- script_handler_t *script_handler;
- struct html_script *nscript;
-
- /* 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)) {
- return DOM_HUBBUB_OK; /* no contents, skip */
- }
-
- nscript = html_process_new_script(c, mimetype, HTML_SCRIPT_INLINE);
- if (nscript == NULL) {
- dom_string_unref(script);
-
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
- return DOM_HUBBUB_NOMEM;
-
- }
-
- nscript->data.string = script;
- nscript->already_started = true;
-
- /* 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));
- }
- return DOM_HUBBUB_OK;
-}
-
-
-/**
- * process script node parser callback
- *
- *
- */
-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, *mimetype;
- dom_hubbub_error err = DOM_HUBBUB_OK;
-
- /* ensure javascript context is available */
- /* We should only ever be here if scripting was enabled for this
- * content so it's correct to make a javascript context if there
- * isn't one already. */
- if (c->jscontext == NULL) {
- union content_msg_data msg_data;
-
- msg_data.jscontext = &c->jscontext;
- content_broadcast(&c->base, CONTENT_MSG_GETCTX, &msg_data);
- NSLOG(netsurf, INFO, "javascript context %p ", c->jscontext);
- if (c->jscontext == NULL) {
- /* no context and it could not be created, abort */
- return DOM_HUBBUB_OK;
- }
- }
-
- NSLOG(netsurf, INFO, "content %p parser %p node %p", c, c->parser,
- node);
-
- exc = dom_element_get_attribute(node, corestring_dom_type, &mimetype);
- if (exc != DOM_NO_ERR || mimetype == NULL) {
- mimetype = dom_string_ref(corestring_dom_text_javascript);
- }
-
- exc = dom_element_get_attribute(node, corestring_dom_src, &src);
- if (exc != DOM_NO_ERR || src == NULL) {
- err = exec_inline_script(c, node, mimetype);
- } else {
- err = exec_src_script(c, node, mimetype, src);
- dom_string_unref(src);
- }
-
- dom_string_unref(mimetype);
-
- return err;
-}
-
-/* exported internal interface documented in render/html_internal.h */
-nserror html_script_free(html_content *html)
-{
- unsigned int i;
-
- for (i = 0; i != html->scripts_count; i++) {
- if (html->scripts[i].mimetype != NULL) {
- dom_string_unref(html->scripts[i].mimetype);
- }
-
- if ((html->scripts[i].type == HTML_SCRIPT_INLINE) &&
- (html->scripts[i].data.string != NULL)) {
-
- dom_string_unref(html->scripts[i].data.string);
-
- } else if ((html->scripts[i].type == HTML_SCRIPT_SYNC) &&
- (html->scripts[i].data.handle != NULL)) {
-
- hlcache_handle_release(html->scripts[i].data.handle);
-
- }
- }
- free(html->scripts);
-
- return NSERROR_OK;
-}
-
-/* exported internal interface documented in render/html_internal.h */
-nserror html_script_invalidate_ctx(html_content *htmlc)
-{
- htmlc->jscontext = NULL;
- return NSERROR_OK;
-}