From 84c29f1d8628fd77de72269b0f424d402fa59a47 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 9 Mar 2015 13:47:12 +0000 Subject: Add invalidate API to html content script handling and use it. The html content script handling needs to invalidate its JavaScript context when the browsing context (browser_window) containing it is either closed or the content fetch is aborted (stopped) Previously the invalidation was only done on browser_window close which resulted in use after free crashes because of the now invalid JavaScript context. --- render/html.c | 32 +++++++++++++++++++++----------- render/html_internal.h | 31 ++++++++++++++++++++++++++++--- render/html_script.c | 28 +++++++++++++++++----------- 3 files changed, 66 insertions(+), 25 deletions(-) diff --git a/render/html.c b/render/html.c index d1a61a4f3..5fb2feabd 100644 --- a/render/html.c +++ b/render/html.c @@ -1106,7 +1106,7 @@ html_begin_conversion(html_content *htmlc) } /* complete script execution */ - html_scripts_exec(htmlc); + html_script_exec(htmlc); /* fire a simple event that bubbles named DOMContentLoaded at * the Document. @@ -1213,12 +1213,21 @@ html_begin_conversion(html_content *htmlc) /** * Stop loading a CONTENT_HTML. + * + * called when the content is aborted. This must clean up any state + * created during the fetch. */ static void html_stop(struct content *c) { html_content *htmlc = (html_content *) c; + /* invalidate the html content reference to the javascript context + * as it is about to become invalid and must not be used any + * more. + */ + html_script_invalidate_ctx(htmlc); + switch (c->status) { case CONTENT_STATUS_LOADING: /* Still loading; simply flag that we've been aborted @@ -1466,7 +1475,7 @@ static void html_destroy(struct content *c) html_css_free_stylesheets(html); /* Free scripts */ - html_free_scripts(html); + html_script_free(html); /* Free objects */ html_object_free_objects(html); @@ -1531,24 +1540,25 @@ html_open(struct content *c, static void html_close(struct content *c) { - html_content *html = (html_content *) c; + html_content *htmlc = (html_content *) c; - selection_clear(&html->sel, false); + selection_clear(&htmlc->sel, false); - if (html->search != NULL) - search_destroy_context(html->search); + if (htmlc->search != NULL) { + search_destroy_context(htmlc->search); + } /* clear the html content reference to the browser window */ - html->bw = NULL; + htmlc->bw = NULL; - /* clear the html content reference to the javascript context + /* invalidate the html content reference to the javascript context * as it is about to become invalid and must not be used any * more. */ - html->jscontext = NULL; + html_script_invalidate_ctx(htmlc); - /* remove all object references from teh html content */ - html_object_close_objects(html); + /* remove all object references from the html content */ + html_object_close_objects(htmlc); } diff --git a/render/html_internal.h b/render/html_internal.h index fd5cf8443..97ac2da55 100644 --- a/render/html_internal.h +++ b/render/html_internal.h @@ -264,9 +264,34 @@ void html_search_clear(struct content *c); /* in render/html_script.c */ -dom_hubbub_error html_process_script(void *ctx, dom_node *node); -void html_free_scripts(html_content *html); -bool html_scripts_exec(html_content *c); +dom_hubbub_error html_process_script(void *ctx, dom_node *node); + +/** + * Attempt script execution for defer and async scripts + * + * execute scripts using algorithm found in: + * http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element + * + * \param htmlc html content. + * \return NSERROR_OK error code. + */ +nserror html_script_exec(html_content *htmlc); + +/** + * Free all script resources and references for a html content. + * + * \param htmlc html content. + * \return NSERROR_OK or error code. + */ +nserror html_script_free(html_content *htmlc); + +/** + * Ensure the html content javascript context is invalidated. + * + * \param htmlc html content. + * \return NSERROR_OK or error code. + */ +nserror html_script_invalidate_ctx(html_content *htmlc); /* in render/html_forms.c */ struct form *html_forms_get_forms(const char *docenc, dom_html_document *doc); diff --git a/render/html_script.c b/render/html_script.c index 4a82bcd70..2ebdffc12 100644 --- a/render/html_script.c +++ b/render/html_script.c @@ -50,20 +50,16 @@ static script_handler_t *select_script_handler(content_type ctype) } -/* attempt defer and async script execution - * - * execute scripts using algorithm found in: - * http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element - * - */ -bool html_scripts_exec(html_content *c) +/* 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 false; + if (c->jscontext == NULL) { + return NSERROR_BAD_PARAMETER; + } for (i = 0, s = c->scripts; i != c->scripts_count; i++, s++) { if (s->already_started) { @@ -102,7 +98,7 @@ bool html_scripts_exec(html_content *c) } } - return true; + return NSERROR_OK; } /* create new html script entry */ @@ -555,7 +551,8 @@ html_process_script(void *ctx, dom_node *node) return err; } -void html_free_scripts(html_content *html) +/* exported internal interface documented in render/html_internal.h */ +nserror html_script_free(html_content *html) { unsigned int i; @@ -577,4 +574,13 @@ void html_free_scripts(html_content *html) } } 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; } -- cgit v1.2.3