summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/content.c25
-rw-r--r--content/content.h7
2 files changed, 29 insertions, 3 deletions
diff --git a/content/content.c b/content/content.c
index 4b58e188f..a8b34a6e7 100644
--- a/content/content.c
+++ b/content/content.c
@@ -287,6 +287,7 @@ struct content * content_create(const char *url)
user_sentinel->next = 0;
c->user_list = user_sentinel;
content_set_status(c, messages_get("Loading"));
+ c->locked = false;
c->fetch = 0;
c->source_data = 0;
c->source_size = 0;
@@ -452,9 +453,10 @@ void content_set_status(struct content *c, const char *status_message, ...)
int len;
va_start(ap, status_message);
- if ((len = vsnprintf(c->status_message, sizeof(c->status_message), status_message, ap)) < 0
- || len >= (int)sizeof(c->status_message))
- c->status_message[sizeof(c->status_message) - 1] = '\0';
+ if ((len = vsnprintf(c->status_message, sizeof (c->status_message),
+ status_message, ap)) < 0 ||
+ (int)sizeof (c->status_message) <= len)
+ c->status_message[sizeof (c->status_message) - 1] = '\0';
va_end(ap);
}
@@ -536,6 +538,7 @@ void content_convert(struct content *c, int width, int height)
assert(c);
assert(c->type < HANDLER_MAP_COUNT);
assert(c->status == CONTENT_STATUS_LOADING);
+ assert(!c->locked);
LOG(("content %s", c->url));
if (c->source_allocated != c->source_size) {
@@ -547,15 +550,20 @@ void content_convert(struct content *c, int width, int height)
}
}
+ c->locked = true;
c->available_width = width;
if (handler_map[c->type].convert) {
if (!handler_map[c->type].convert(c, width, height)) {
c->status = CONTENT_STATUS_ERROR;
+ c->locked = false;
return;
}
} else {
c->status = CONTENT_STATUS_DONE;
}
+ c->locked = false;
+
+ c->size = talloc_total_size(c);
assert(c->status == CONTENT_STATUS_READY ||
c->status == CONTENT_STATUS_DONE);
@@ -577,11 +585,14 @@ void content_reformat(struct content *c, int width, int height)
assert(c != 0);
assert(c->status == CONTENT_STATUS_READY ||
c->status == CONTENT_STATUS_DONE);
+ assert(!c->locked);
+ c->locked = true;
c->available_width = width;
if (handler_map[c->type].reformat) {
handler_map[c->type].reformat(c, width, height);
content_broadcast(c, CONTENT_MSG_REFORMAT, data);
}
+ c->locked = false;
}
@@ -604,6 +615,9 @@ void content_clean(void)
for (c = content_list; c; c = next) {
next = c->next;
+ /* this function must not be called from a content function */
+ assert(!c->locked);
+
if (c->user_list->next && c->status != CONTENT_STATUS_ERROR)
/* content has users */
continue;
@@ -650,6 +664,7 @@ void content_destroy(struct content *c)
{
assert(c);
LOG(("content %p %s", c, c->url));
+ assert(!c->locked);
if (c->fetch)
fetch_abort(c->fetch);
@@ -679,6 +694,7 @@ void content_reset(struct content *c)
{
assert(c != 0);
LOG(("content %p %s", c, c->url));
+ assert(!c->locked);
if (c->type < HANDLER_MAP_COUNT && handler_map[c->type].destroy)
handler_map[c->type].destroy(c);
c->type = CONTENT_UNKNOWN;
@@ -732,6 +748,9 @@ bool content_redraw(struct content *c, int x, int y,
float scale, unsigned long background_colour)
{
assert(c != 0);
+ if (c->locked)
+ /* not safe to attempt redraw */
+ return true;
if (handler_map[c->type].redraw)
return handler_map[c->type].redraw(c, x, y, width, height,
clip_x0, clip_y0, clip_x1, clip_y1, scale,
diff --git a/content/content.h b/content/content.h
index 0c6833e67..4bda90dfd 100644
--- a/content/content.h
+++ b/content/content.h
@@ -92,6 +92,10 @@
* if an error occurs, must broadcast CONTENT_MSG_ERROR and return false.
* Optionally use warn_user() for serious errors. The _destroy function will
* be called soon after.
+ *
+ * Each content structure is allocated using talloc, and all data related to a
+ * content should be allocated as a child block of the content structure using
+ * talloc. This will ensure that all memory used by a page is freed.
*/
#ifndef _NETSURF_DESKTOP_CONTENT_H_
@@ -235,6 +239,9 @@ struct content {
conversions currently in progress. */
struct content_user *user_list; /**< List of users. */
char status_message[80]; /**< Text for status bar. */
+ /** Content is being processed: data structures may be inconsistent
+ * and content must not be redrawn or modified. */
+ bool locked;
struct fetch *fetch; /**< Associated fetch, or 0. */
char *source_data; /**< Source data, as received. */