summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/content.c1
-rw-r--r--content/content.h5
-rw-r--r--desktop/browser.c26
-rw-r--r--render/html.c116
4 files changed, 148 insertions, 0 deletions
diff --git a/content/content.c b/content/content.c
index 70f280c3d..11effac45 100644
--- a/content/content.c
+++ b/content/content.c
@@ -295,6 +295,7 @@ struct content * content_create(const char *url)
c->width = 0;
c->height = 0;
c->available_width = 0;
+ c->refresh = 0;
c->bitmap = 0;
c->fresh = false;
c->size = sizeof(struct content);
diff --git a/content/content.h b/content/content.h
index 897b81370..3e24ccbc0 100644
--- a/content/content.h
+++ b/content/content.h
@@ -150,6 +150,7 @@ typedef enum {
CONTENT_MSG_REFORMAT, /**< content_reformat done */
CONTENT_MSG_REDRAW, /**< needs redraw (eg. new animation frame) */
CONTENT_MSG_NEWPTR, /**< address of structure has changed */
+ CONTENT_MSG_REFRESH, /**< wants refresh */
#ifdef WITH_AUTH
CONTENT_MSG_AUTH /**< authentication required */
#endif
@@ -173,6 +174,7 @@ union content_msg_data {
float object_width, object_height;
} redraw;
char *auth_realm; /**< Realm, for CONTENT_MSG_AUTH. */
+ int delay; /**< Minimum delay, for CONTENT_MSG_REFRESH */
};
/** Linked list of users of a content. */
@@ -233,6 +235,9 @@ struct content {
#endif
} data;
+ /**< URL for refresh request, in standard form as from url_join. */
+ char *refresh;
+
/** Bitmap, for various image contents. */
struct bitmap *bitmap;
diff --git a/desktop/browser.c b/desktop/browser.c
index 41b1baed5..d4cec3fcd 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -51,6 +51,7 @@ struct browser_window *current_redraw_browser;
static void browser_window_callback(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data);
+static void browser_window_refresh(void *p);
static void browser_window_convert_to_download(struct browser_window *bw);
static void browser_window_start_throbber(struct browser_window *bw);
static void browser_window_stop_throbber(struct browser_window *bw);
@@ -414,6 +415,11 @@ void browser_window_callback(content_msg msg, struct content *c,
break;
#endif
+ case CONTENT_MSG_REFRESH:
+ schedule(data.delay * 100,
+ browser_window_refresh, bw);
+ break;
+
default:
assert(0);
}
@@ -421,6 +427,26 @@ void browser_window_callback(content_msg msg, struct content *c,
/**
+ * Refresh browser window
+ *
+ * \param p Browser window to refresh
+ */
+
+void browser_window_refresh(void *p)
+{
+ struct browser_window *bw = p;
+
+ assert(bw->current_content->status == CONTENT_STATUS_READY ||
+ bw->current_content->status == CONTENT_STATUS_DONE);
+
+ /* mark this content as invalid so it gets flushed from the cache */
+ bw->current_content->fresh = false;
+
+ browser_window_go(bw, bw->current_content->refresh,
+ bw->current_content->url);
+}
+
+/**
* Transfer the loading_content to a new download window.
*/
diff --git a/render/html.c b/render/html.c
index a2dac2ec5..c092df8c2 100644
--- a/render/html.c
+++ b/render/html.c
@@ -20,6 +20,7 @@
#include "netsurf/content/content.h"
#include "netsurf/content/fetch.h"
#include "netsurf/content/fetchcache.h"
+#include "netsurf/desktop/browser.h"
#include "netsurf/desktop/gui.h"
#include "netsurf/desktop/options.h"
#include "netsurf/render/box.h"
@@ -40,6 +41,7 @@ static bool html_set_parser_encoding(struct content *c, const char *encoding);
static const char *html_detect_encoding(const char *data, unsigned int size);
static void html_convert_css_callback(content_msg msg, struct content *css,
intptr_t p1, intptr_t p2, union content_msg_data data);
+static bool html_meta_refresh(struct content *c, xmlNode *head);
static bool html_head(struct content *c, xmlNode *head);
static bool html_find_stylesheets(struct content *c, xmlNode *head);
static void html_object_callback(content_msg msg, struct content *object,
@@ -50,6 +52,7 @@ static void html_object_failed(struct box *box, struct content *content,
bool background);
static bool html_object_type_permitted(const content_type type,
const content_type *permitted_types);
+static void html_object_refresh(void *p);
static bool html_find_frame(struct content *c, const char *frame,
struct content **page, unsigned int *i);
@@ -308,6 +311,10 @@ bool html_convert(struct content *c, int width, int height)
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
+
+ /* handle meta refresh */
+ if (!html_meta_refresh(c, head))
+ return false;
}
/* get stylesheets */
@@ -362,6 +369,90 @@ bool html_convert(struct content *c, int width, int height)
return true;
}
+/**
+ * Search for meta refresh
+ *
+ * \param c content structure
+ * \param head xml node of head element
+ * \return true on success, false otherwise (error reported)
+ */
+
+bool html_meta_refresh(struct content *c, xmlNode *head)
+{
+ xmlNode *n;
+ xmlChar *equiv, *content;
+ union content_msg_data msg_data;
+ char *url, *end, *refresh;
+ url_func_result res;
+
+ for (n = head == 0 ? 0 : head->children; n; n = n->next) {
+ if (n->type != XML_ELEMENT_NODE)
+ continue;
+
+ if (strcmp((const char *)n->name, "meta"))
+ continue;
+
+ equiv = xmlGetProp(n, (const xmlChar *)"http-equiv");
+ if (!equiv)
+ continue;
+
+ if (strcasecmp((const char *)equiv, "refresh")) {
+ xmlFree(equiv);
+ continue;
+ }
+
+ xmlFree(equiv);
+
+ content = xmlGetProp(n, (const xmlChar *)"content");
+ if (!content)
+ continue;
+
+ end = (char *)content + strlen(content);
+
+ msg_data.delay = (int)strtol((char *) content, &url, 10);
+
+ for ( ; url <= end - 4; url++) {
+ if (!strncasecmp(url, "url=", 4))
+ break;
+ }
+
+ if (url <= end - 4) {
+ res = url_join(url + 4, c->data.html.base_url,
+ &refresh);
+
+ xmlFree(content);
+
+ if (res == URL_FUNC_NOMEM) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c,
+ CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+ else if (res == URL_FUNC_FAILED) {
+ /* This isn't fatal so carry on looking */
+ continue;
+ }
+
+ c->refresh = talloc_strdup(c, refresh);
+
+ free(refresh);
+
+ if (!c->refresh) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c,
+ CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ content_broadcast(c, CONTENT_MSG_REFRESH, msg_data);
+ break;
+ }
+
+ xmlFree(content);
+ }
+
+ return true;
+}
/**
* Process elements in <head>.
@@ -1018,6 +1109,13 @@ void html_object_callback(content_msg msg, struct content *object,
break;
#endif
+ case CONTENT_MSG_REFRESH:
+ if (object->type == CONTENT_HTML)
+ /* only for HTML objects */
+ schedule(data.delay * 100,
+ html_object_refresh, object);
+ break;
+
default:
assert(0);
}
@@ -1178,6 +1276,24 @@ bool html_object_type_permitted(const content_type type,
/**
+ * schedule() callback for object refresh
+ */
+
+void html_object_refresh(void *p)
+{
+ struct content *c = (struct content *)p;
+
+ assert(c->type == CONTENT_HTML && c->refresh);
+
+ c->fresh = false;
+
+ if (!html_replace_object(c->data.html.page, c->data.html.index,
+ c->refresh, 0, 0)) {
+ /** \todo handle memory exhaustion */
+ }
+}
+
+/**
* Stop loading a CONTENT_HTML in state READY.
*/