diff --git a/content/handlers/html/box.h b/content/handlers/html/box.h
index 6939cfe1a..089c66433 100644
--- a/content/handlers/html/box.h
+++ b/content/handlers/html/box.h
@@ -359,7 +359,8 @@ bool box_vscrollbar_present(const struct box *box);
bool box_hscrollbar_present(const struct box *box);
nserror dom_to_box(struct dom_node *n, struct html_content *c,
- box_construct_complete_cb cb);
+ box_construct_complete_cb cb, void **box_conversion_context);
+nserror cancel_dom_to_box(void *box_conversion_context);
bool box_normalise_block(
struct box *block,
diff --git a/content/handlers/html/box_construct.c b/content/handlers/html/box_construct.c
index 1f15d82b7..f0d68ac2e 100644
--- a/content/handlers/html/box_construct.c
+++ b/content/handlers/html/box_construct.c
@@ -163,10 +163,12 @@ static const struct element_entry element_table[] = {
* \return netsurf error code indicating status of call
*/
-nserror dom_to_box(dom_node *n, html_content *c, box_construct_complete_cb cb)
+nserror dom_to_box(dom_node *n, html_content *c, box_construct_complete_cb cb, void **box_conversion_context)
{
struct box_construct_ctx *ctx;
+ assert(box_conversion_context != NULL);
+
if (c->bctx == NULL) {
/* create a context allocation for this box tree */
c->bctx = talloc_zero(0, int);
@@ -186,9 +188,28 @@ nserror dom_to_box(dom_node *n, html_content *c, box_construct_complete_cb cb)
ctx->cb = cb;
ctx->bctx = c->bctx;
+ *box_conversion_context = ctx;
+
return guit->misc->schedule(0, (void *)convert_xml_to_box, ctx);
}
+nserror cancel_dom_to_box(void *box_conversion_context)
+{
+ struct box_construct_ctx *ctx = box_conversion_context;
+ nserror err;
+
+ err = guit->misc->schedule(-1, (void *)convert_xml_to_box, ctx);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ dom_node_unref(ctx->n);
+ free(ctx);
+
+ return NSERROR_OK;
+}
+
+
/* mapping from CSS display to box type
* this table must be in sync with libcss' css_display enum */
static const box_type box_map[] = {
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index ed48af20e..33dcf2aaa 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -115,6 +115,8 @@ static void html_box_convert_done(html_content *c, bool success)
NSLOG(netsurf, INFO, "Done XML to box (%p)", c);
+ c->box_conversion_context = NULL;
+
/* Clean up and report error if unsuccessful or aborted */
if ((success == false) || (c->aborted)) {
html_object_free_objects(c);
@@ -656,7 +658,7 @@ void html_finish_conversion(html_content *htmlc)
html_get_dimensions(htmlc);
- error = dom_to_box(html, htmlc, html_box_convert_done);
+ error = dom_to_box(html, htmlc, html_box_convert_done, &htmlc->box_conversion_context);
if (error != NSERROR_OK) {
NSLOG(netsurf, INFO, "box conversion failed");
dom_node_unref(html);
@@ -1710,6 +1712,13 @@ static void html_destroy(struct content *c)
NSLOG(netsurf, INFO, "content %p", c);
+ /* If we're still converting a layout, cancel it */
+ if (html->box_conversion_context != NULL) {
+ if (cancel_dom_to_box(html->box_conversion_context) != NSERROR_OK) {
+ NSLOG(netsurf, CRITICAL, "WARNING, Unable to cancel conversion context, browser may crash");
+ }
+ }
+
/* Destroy forms */
for (f = html->forms; f != NULL; f = g) {
g = f->prev;
diff --git a/content/handlers/html/html_internal.h b/content/handlers/html/html_internal.h
index 7a8d95612..fd6354a5a 100644
--- a/content/handlers/html/html_internal.h
+++ b/content/handlers/html/html_internal.h
@@ -138,6 +138,10 @@ typedef struct html_content {
/** A talloc context purely for the render box tree */
int *bctx;
+ /** A context pointer for the box conversion, NULL if no conversion
+ * is in progress.
+ */
+ void *box_conversion_context;
/** Box tree, or NULL. */
struct box *layout;
/** Document background colour. */