summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2004-06-10 23:55:23 +0000
committerJames Bursa <james@netsurf-browser.org>2004-06-10 23:55:23 +0000
commitd938fe135b5e0fc5b4c957beac2445ae5e6d54ed (patch)
tree823ec259b37319d7790303c5a7b84528dae52fd6
parentd58147aa584b8642a94d8c701d18e09252fb85f0 (diff)
downloadnetsurf-d938fe135b5e0fc5b4c957beac2445ae5e6d54ed.tar.gz
netsurf-d938fe135b5e0fc5b4c957beac2445ae5e6d54ed.tar.bz2
[project @ 2004-06-10 23:55:23 by bursa]
Split fetchcache() into fetchcache() and fetchcache_go() to solve problems of callbacks being called before fetchcache() returns. Fix <style> breakage. Error handling fixes & improvements. svn path=/import/netsurf/; revision=957
-rw-r--r--content/content.c1
-rw-r--r--content/fetch.c12
-rw-r--r--content/fetchcache.c166
-rw-r--r--content/fetchcache.h36
-rw-r--r--css/css.c41
-rw-r--r--desktop/browser.c34
-rw-r--r--render/html.c140
7 files changed, 226 insertions, 204 deletions
diff --git a/content/content.c b/content/content.c
index 3974e90fd..5b8956ab5 100644
--- a/content/content.c
+++ b/content/content.c
@@ -304,6 +304,7 @@ bool content_set_type(struct content *c, content_type type,
if (handler_map[type].create) {
if (!handler_map[type].create(c, params)) {
+ c->type = CONTENT_UNKNOWN;
c->status = CONTENT_STATUS_ERROR;
return false;
}
diff --git a/content/fetch.c b/content/fetch.c
index b42e48ea7..f68dea739 100644
--- a/content/fetch.c
+++ b/content/fetch.c
@@ -302,12 +302,6 @@ struct fetch * fetch_start(char *url, char *referer,
}
}
- fetch->next = fetch_list;
- if (fetch_list != 0)
- fetch_list->prev = fetch;
- fetch_list = fetch;
- fetch_active = true;
-
/* create the curl easy handle */
fetch->curl_handle = curl_easy_duphandle(fetch_blank_curl);
if (!fetch->curl_handle)
@@ -321,6 +315,12 @@ struct fetch * fetch_start(char *url, char *referer,
codem = curl_multi_add_handle(curl_multi, fetch->curl_handle);
assert(codem == CURLM_OK || codem == CURLM_CALL_MULTI_PERFORM);
+ fetch->next = fetch_list;
+ if (fetch_list != 0)
+ fetch_list->prev = fetch;
+ fetch_list = fetch;
+ fetch_active = true;
+
return fetch;
failed:
diff --git a/content/fetchcache.c b/content/fetchcache.c
index 359b59809..1ddd2fe7a 100644
--- a/content/fetchcache.c
+++ b/content/fetchcache.c
@@ -36,50 +36,41 @@ static void fetchcache_error_page(struct content *c, const char *error);
/**
- * Retrieve a URL or fetch, convert, and cache it.
- *
- * The referer may be 0.
+ * Retrieve a URL or prepare to fetch, convert, and cache it.
*
* The caller must supply a callback function which is called when anything
* interesting happens to the content which is returned. See content.h.
*
- * If an error occurs immediately, 0 may be returned. Later errors will be
- * reported via the callback.
+ * \param url address to fetch
+ * \param callback function to call when anything interesting happens to
+ * the new content
+ * \param p1 user parameter for callback
+ * \param p2 user parameter for callback
+ * \param width available space
+ * \param height available space
+ * \param no_error_pages if an error occurs, send CONTENT_MSG_ERROR instead
+ * of generating an error page
+ * \param post_urlenc url encoded post data, or 0 if none
+ * \param post_multipart multipart post data, or 0 if none
+ * \param cookies send and accept cookies
+ * \return a new content, or 0 on memory exhaustion
*
- * \param url address to fetch
- * \param referer url of referring page, or 0 if none
- * \param callback function to call when anything interesting happens to
- * the new content
- * \param p1 user parameter for callback
- * \param p2 user parameter for callback
- * \param width available space
- * \param height available space
- * \param no_error_pages if an error occurs, send CONTENT_MSG_ERROR instead
- * of generating an error page
- * \param post_urlenc url encoded post data, or 0 if none
- * \param post_multipart multipart post data, or 0 if none
- * \param cookies send and accept cookies
- * \return a new content, or 0 if an error occurred
+ * On success, call fetchcache_go() to start work on the new content.
*/
-struct content * fetchcache(const char *url, char *referer,
+struct content * fetchcache(const char *url,
void (*callback)(content_msg msg, struct content *c, void *p1,
void *p2, union content_msg_data data),
- void *p1, void *p2, unsigned long width, unsigned long height,
- bool no_error_pages
-#ifdef WITH_POST
- , char *post_urlenc,
- struct form_successful_control *post_multipart
-#endif
-#ifdef WITH_COOKIES
- ,bool cookies
-#endif
- )
+ void *p1, void *p2,
+ int width, int height,
+ bool no_error_pages,
+ char *post_urlenc,
+ struct form_successful_control *post_multipart,
+ bool cookies)
{
struct content *c;
char *url1;
char *hash;
- char error_message[500];
url1 = strdup(url);
if (!url1)
@@ -91,12 +82,9 @@ struct content * fetchcache(const char *url, char *referer,
LOG(("url %s", url1));
-#ifdef WITH_POST
- if (!post_urlenc && !post_multipart)
-#endif
- {
+ if (!post_urlenc && !post_multipart) {
c = cache_get(url1);
- if (c != 0) {
+ if (c) {
free(url1);
content_add_user(c, callback, p1, p2);
return c;
@@ -110,35 +98,93 @@ struct content * fetchcache(const char *url, char *referer,
}
content_add_user(c, callback, p1, p2);
-#ifdef WITH_POST
if (!post_urlenc && !post_multipart)
-#endif
cache_put(c);
c->width = width;
c->height = height;
c->no_error_pages = no_error_pages;
- c->fetch = fetch_start(url1, referer, fetchcache_callback, c, no_error_pages
-#ifdef WITH_POST
- ,post_urlenc, post_multipart
-#endif
-#ifdef WITH_COOKIES
- ,cookies
-#endif
- );
- if (!c->fetch) {
- LOG(("warning: fetch_start failed"));
- c->status = CONTENT_STATUS_ERROR;
- if (no_error_pages) {
- free(url1);
- return 0;
+
+ return c;
+}
+
+
+/**
+ * Start fetching and converting a content.
+ *
+ * \param url address to fetch
+ * \param referer referring URL, or 0
+ * \param callback function to call when anything interesting happens to
+ * the new content
+ * \param p1 user parameter for callback
+ * \param p2 user parameter for callback
+ * \param post_urlenc url encoded post data, or 0 if none
+ * \param post_multipart multipart post data, or 0 if none
+ * \param cookies send and accept cookies
+ *
+ * Errors will be sent back through the callback.
+ */
+
+void fetchcache_go(struct content *content, char *referer,
+ void (*callback)(content_msg msg, struct content *c, void *p1,
+ void *p2, union content_msg_data data),
+ void *p1, void *p2,
+ char *post_urlenc,
+ struct form_successful_control *post_multipart,
+ bool cookies)
+{
+ char error_message[500];
+ union content_msg_data msg_data;
+
+ LOG(("url %s, status %s", content->url,
+ content_status_name[content->status]));
+
+ if (content->status == CONTENT_STATUS_TYPE_UNKNOWN && content->fetch) {
+ /* fetching, but not yet received any response:
+ * no action required */
+
+ } else if (content->status == CONTENT_STATUS_TYPE_UNKNOWN) {
+ /* brand new content: start fetch */
+ content->fetch = fetch_start(content->url, referer,
+ fetchcache_callback, content,
+ content->no_error_pages,
+ post_urlenc, post_multipart, cookies);
+ if (!content->fetch) {
+ LOG(("warning: fetch_start failed"));
+ snprintf(error_message, sizeof error_message,
+ messages_get("InvalidURL"),
+ content->url);
+ if (content->no_error_pages) {
+ content->status = CONTENT_STATUS_ERROR;
+ msg_data.error = error_message;
+ content_broadcast(content, CONTENT_MSG_ERROR,
+ msg_data);
+ } else {
+ fetchcache_error_page(content, error_message);
+ }
}
- snprintf(error_message, sizeof error_message,
- messages_get("InvalidURL"), url1);
- fetchcache_error_page(c, error_message);
+
+ /* in these remaining cases, we have to 'catch up' with the content's
+ * status, ie. send the same messages as if the content was
+ * gradually getting to the current status from TYPE_UNKNOWN */
+ } else if (content->status == CONTENT_STATUS_LOADING) {
+ callback(CONTENT_MSG_LOADING, content, p1, p2, msg_data);
+
+ } else if (content->status == CONTENT_STATUS_READY) {
+ callback(CONTENT_MSG_LOADING, content, p1, p2, msg_data);
+ callback(CONTENT_MSG_READY, content, p1, p2, msg_data);
+
+ } else if (content->status == CONTENT_STATUS_DONE) {
+ callback(CONTENT_MSG_LOADING, content, p1, p2, msg_data);
+ callback(CONTENT_MSG_READY, content, p1, p2, msg_data);
+ callback(CONTENT_MSG_DONE, content, p1, p2, msg_data);
+
+ } else if (content->status == CONTENT_STATUS_ERROR) {
+ /* shouldn't usually occur */
+ msg_data.error = messages_get("MiscError");
+ callback(CONTENT_MSG_ERROR, content, p1, p2, msg_data);
+
}
- free(url1);
- return c;
}
@@ -327,8 +373,10 @@ void fetchcache_error_page(struct content *c, const char *error)
if ((length = snprintf(error_page, sizeof(error_page),
messages_get("ErrorPage"), error)) < 0)
length = 0;
- content_set_type(c, CONTENT_HTML, "text/html", params);
- content_process_data(c, error_page, length);
+ if (!content_set_type(c, CONTENT_HTML, "text/html", params))
+ return;
+ if (!content_process_data(c, error_page, length))
+ return;
content_convert(c, c->width, c->height);
}
diff --git a/content/fetchcache.h b/content/fetchcache.h
index 3fadc3459..f20ab6cf9 100644
--- a/content/fetchcache.h
+++ b/content/fetchcache.h
@@ -2,40 +2,40 @@
* This file is part of NetSurf, http://netsurf.sourceforge.net/
* Licensed under the GNU General Public License,
* http://www.opensource.org/licenses/gpl-license
- * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
*/
/** \file
* High-level fetching, caching and conversion (interface).
*
- * The fetchcache() function retrieves a URL from the cache, or fetches,
- * converts, and caches it if not cached.
+ * The fetchcache() / fetchcache_go() pair of functions retrieve a URL from
+ * the cache, or fetch, convert, and cache it if not cached.
*/
#ifndef _NETSURF_DESKTOP_FETCHCACHE_H_
#define _NETSURF_DESKTOP_FETCHCACHE_H_
#include <stdbool.h>
-#include "netsurf/utils/config.h"
#include "netsurf/content/content.h"
-#ifdef WITH_POST
struct form_successful_control;
-#endif
-struct content * fetchcache(const char *url, char *referer,
+void fetchcache_init(void);
+struct content * fetchcache(const char *url,
void (*callback)(content_msg msg, struct content *c, void *p1,
void *p2, union content_msg_data data),
- void *p1, void *p2, unsigned long width, unsigned long height,
- bool no_error_pages
-#ifdef WITH_POST
- , char *post_urlenc,
- struct form_successful_control *post_multipart
-#endif
-#ifdef WITH_COOKIES
- ,bool cookies
-#endif
- );
-void fetchcache_init(void);
+ void *p1, void *p2,
+ int width, int height,
+ bool no_error_pages,
+ char *post_urlenc,
+ struct form_successful_control *post_multipart,
+ bool cookies);
+void fetchcache_go(struct content *content, char *referer,
+ void (*callback)(content_msg msg, struct content *c, void *p1,
+ void *p2, union content_msg_data data),
+ void *p1, void *p2,
+ char *post_urlenc,
+ struct form_successful_control *post_multipart,
+ bool cookies);
#endif
diff --git a/css/css.c b/css/css.c
index 8239d77bf..3072c3a47 100644
--- a/css/css.c
+++ b/css/css.c
@@ -560,19 +560,15 @@ void css_atimport(struct content *c, struct css_node *node)
c->data.css.import_count++;
i = c->data.css.import_count - 1;
c->data.css.import_url[i] = url1;
- c->data.css.import_content[i] = fetchcache(
- c->data.css.import_url[i], c->url, css_atimport_callback,
- c, (void*)i, c->width, c->height, true
-#ifdef WITH_POST
- , 0, 0
-#endif
-#ifdef WITH_COOKIES
- , false
-#endif
- );
- if (c->data.css.import_content[i] &&
- c->data.css.import_content[i]->status != CONTENT_STATUS_DONE)
+ c->data.css.import_content[i] = fetchcache(c->data.css.import_url[i],
+ css_atimport_callback, c, (void *) i,
+ c->width, c->height, true, 0, 0, false);
+ if (c->data.css.import_content[i]) {
c->active++;
+ fetchcache_go(c->data.css.import_content[i], c->url,
+ css_atimport_callback, c, (void *) i,
+ 0, 0, false);
+ }
free(url);
}
@@ -625,18 +621,17 @@ void css_atimport_callback(content_msg msg, struct content *css,
return;
}
c->data.css.import_content[i] = fetchcache(
- c->data.css.import_url[i], c->url, css_atimport_callback,
- c, (void*)i, css->width, css->height, true
-#ifdef WITH_POST
- , 0, 0
-#endif
-#ifdef WITH_COOKIES
- , false
-#endif
- );
- if (c->data.css.import_content[i] &&
- c->data.css.import_content[i]->status != CONTENT_STATUS_DONE)
+ c->data.css.import_url[i],
+ css_atimport_callback, c, (void *) i,
+ css->width, css->height, true, 0, 0,
+ false);
+ if (c->data.css.import_content[i]) {
c->active++;
+ fetchcache_go(c->data.css.import_content[i],
+ c->url, css_atimport_callback,
+ c, (void *) i,
+ 0, 0, false);
+ }
break;
default:
diff --git a/desktop/browser.c b/desktop/browser.c
index 2c8c28441..499d07997 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -152,7 +152,8 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
{
struct content *c;
char *url2;
- union content_msg_data data;
+
+ LOG(("bw %p, url %s", bw, url));
url2 = url_normalize(url);
if (!url2) {
@@ -165,36 +166,21 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
browser_window_set_status(bw, messages_get("Loading"));
bw->history_add = history_add;
bw->time0 = clock();
- if (strncmp(url2, "about:", 6) == 0) {
- c = about_create(url2, browser_window_callback, bw, 0,
- gui_window_get_width(bw->window), 0);
- }
- else {
- c = fetchcache(url2, 0,
- browser_window_callback, bw, 0,
- gui_window_get_width(bw->window), 0,
- false,
- post_urlenc, post_multipart,
- true);
- }
+ c = fetchcache(url2, browser_window_callback, bw, 0,
+ gui_window_get_width(bw->window), 0,
+ false,
+ post_urlenc, post_multipart, true);
free(url2);
if (!c) {
- browser_window_set_status(bw, messages_get("FetchFailed"));
+ browser_window_set_status(bw, messages_get("NoMemory"));
+ warn_user("NoMemory", 0);
return;
}
bw->loading_content = c;
browser_window_start_throbber(bw);
- if (c->status == CONTENT_STATUS_READY) {
- browser_window_callback(CONTENT_MSG_READY, c, bw, 0, data);
-
- } else if (c->status == CONTENT_STATUS_DONE) {
- browser_window_callback(CONTENT_MSG_READY, c, bw, 0, data);
- if (c->type == CONTENT_OTHER)
- download_window_callback(CONTENT_MSG_DONE, c, bw, 0, data);
- else
- browser_window_callback(CONTENT_MSG_DONE, c, bw, 0, data);
- }
+ fetchcache_go(c, 0, browser_window_callback, bw, 0,
+ post_urlenc, post_multipart, true);
}
diff --git a/render/html.c b/render/html.c
index 0f8a87a8a..c3e94bd15 100644
--- a/render/html.c
+++ b/render/html.c
@@ -313,19 +313,13 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
#else
"file:///home/james/Projects/netsurf/CSS",
#endif
- c->url,
- html_convert_css_callback,
- c, 0, c->width, c->height, true
-#ifdef WITH_POST
- , 0, 0
-#endif
-#ifdef WITH_COOKIES
- , false
-#endif
- );
- assert(c->data.html.stylesheet_content[0] != 0);
- if (c->data.html.stylesheet_content[0]->status != CONTENT_STATUS_DONE)
- c->active++;
+ html_convert_css_callback, c, 0,
+ c->width, c->height, true, 0, 0, false);
+ assert(c->data.html.stylesheet_content[0]);
+ c->active++;
+ fetchcache_go(c->data.html.stylesheet_content[0], 0,
+ html_convert_css_callback, c, 0,
+ 0, 0, false);
for (node = head == 0 ? 0 : head->children; node != 0; node = node->next) {
if (node->type != XML_ELEMENT_NODE)
@@ -377,19 +371,18 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
/* start fetch */
c->data.html.stylesheet_content = xrealloc(c->data.html.stylesheet_content,
(i + 1) * sizeof(*c->data.html.stylesheet_content));
- c->data.html.stylesheet_content[i] = fetchcache(url, c->url,
- html_convert_css_callback, c, (void*)i,
- c->width, c->height, true
-#ifdef WITH_POST
- , 0, 0
-#endif
-#ifdef WITH_COOKIES
- , false
-#endif
- );
- if (c->data.html.stylesheet_content[i] &&
- c->data.html.stylesheet_content[i]->status != CONTENT_STATUS_DONE)
+ c->data.html.stylesheet_content[i] = fetchcache(url,
+ html_convert_css_callback,
+ c, (void *) i, c->width, c->height,
+ true, 0, 0, false);
+ if (c->data.html.stylesheet_content[i]) {
c->active++;
+ fetchcache_go(c->data.html.stylesheet_content[i],
+ c->url,
+ html_convert_css_callback,
+ c, (void *) i,
+ 0, 0, false);
+ }
free(url);
i++;
@@ -418,19 +411,27 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
if (c->data.html.stylesheet_content[1] == 0) {
const char *params[] = { 0 };
c->data.html.stylesheet_content[1] =
- content_create(c->data.html.base_url);
+ content_create(c->data.html.
+ base_url);
if (!c->data.html.stylesheet_content[1])
- return;
- content_set_type(c->data.html.stylesheet_content[1],
- CONTENT_CSS, "text/css", params);
+ return false;
+ if (!content_set_type(c->data.html.
+ stylesheet_content[1],
+ CONTENT_CSS, "text/css",
+ params))
+ return false;
}
/* can't just use xmlNodeGetContent(node), because that won't give
* the content of comments which may be used to 'hide' the content */
for (node2 = node->children; node2 != 0; node2 = node2->next) {
data = xmlNodeGetContent(node2);
- content_process_data(c->data.html.stylesheet_content[1],
- data, strlen(data));
+ if (!content_process_data(c->data.html.
+ stylesheet_content[1],
+ data, strlen(data))) {
+ xmlFree(data);
+ return false;
+ }
xmlFree(data);
}
}
@@ -441,8 +442,11 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
if (c->data.html.stylesheet_content[1] != 0) {
if (css_convert(c->data.html.stylesheet_content[1], c->width,
c->height)) {
+ content_add_user(c->data.html.stylesheet_content[1],
+ html_convert_css_callback,
+ c, (void *) 1);
+ } else {
/* conversion failed */
- content_destroy(c->data.html.stylesheet_content[1]);
c->data.html.stylesheet_content[1] = 0;
}
}
@@ -512,19 +516,18 @@ void html_convert_css_callback(content_msg msg, struct content *css,
case CONTENT_MSG_REDIRECT:
c->active--;
c->data.html.stylesheet_content[i] = fetchcache(
- data.redirect, c->url,
+ data.redirect,
html_convert_css_callback,
- c, (void*)i, css->width, css->height, true
-#ifdef WITH_POST
- , 0, 0
-#endif
-#ifdef WITH_COOKIES
- , false
-#endif
- );
- if (c->data.html.stylesheet_content[i] != 0 &&
- c->data.html.stylesheet_content[i]->status != CONTENT_STATUS_DONE)
+ c, (void *) i, css->width, css->height,
+ true, 0, 0, false);
+ if (c->data.html.stylesheet_content[i]) {
c->active++;
+ fetchcache_go(c->data.html.stylesheet_content[i],
+ c->url,
+ html_convert_css_callback,
+ c, (void *) i,
+ 0, 0, false);
+ }
break;
#ifdef WITH_AUTH
@@ -560,7 +563,6 @@ void html_fetch_object(struct content *c, char *url, struct box *box,
bool background)
{
unsigned int i = c->data.html.object_count;
- union content_msg_data data;
/* add to object list */
c->data.html.object = xrealloc(c->data.html.object,
@@ -571,23 +573,14 @@ void html_fetch_object(struct content *c, char *url, struct box *box,
c->data.html.object[i].background = background;
/* start fetch */
- c->data.html.object[i].content = fetchcache(url, c->url,
- html_object_callback,
- c, (void*)i, available_width, available_height,
- true
-#ifdef WITH_POST
- , 0, 0
-#endif
-#ifdef WITH_COOKIES
- , false
-#endif
- );
-
+ c->data.html.object[i].content = fetchcache(url, html_object_callback,
+ c, (void *) i, available_width, available_height,
+ true, 0, 0, false);
if (c->data.html.object[i].content) {
c->active++;
- if (c->data.html.object[i].content->status == CONTENT_STATUS_DONE)
- html_object_callback(CONTENT_MSG_DONE,
- c->data.html.object[i].content, c, (void*)i, data);
+ fetchcache_go(c->data.html.object[i].content, c->url,
+ html_object_callback, c, (void *) i,
+ 0, 0, false);
}
c->data.html.object_count++;
}
@@ -623,8 +616,13 @@ void html_object_callback(content_msg msg, struct content *object,
case CONTENT_MSG_READY:
if (object->type == CONTENT_HTML) {
- html_object_done(box, object, c->data.html.object[i].background);
- content_reformat(c, c->available_width, 0);
+ html_object_done(box, object,
+ c->data.html.object[i].background);
+ if (c->status == CONTENT_STATUS_READY ||
+ c->status ==
+ CONTENT_STATUS_DONE)
+ content_reformat(c,
+ c->available_width, 0);
}
break;
@@ -653,21 +651,15 @@ void html_object_callback(content_msg msg, struct content *object,
free(c->data.html.object[i].url);
c->data.html.object[i].url = xstrdup(data.redirect);
c->data.html.object[i].content = fetchcache(
- data.redirect, c->url,
- html_object_callback,
- c, (void*)i, 0, 0, true
-#ifdef WITH_POST
- , 0, 0
-#endif
-#ifdef WITH_COOKIES
- , false
-#endif
- );
+ data.redirect, html_object_callback,
+ c, (void * ) i, 0, 0, true, 0, 0,
+ false);
if (c->data.html.object[i].content) {
c->active++;
- if (c->data.html.object[i].content->status == CONTENT_STATUS_DONE)
- html_object_callback(CONTENT_MSG_DONE,
- c->data.html.object[i].content, c, (void*)i, data);
+ fetchcache_go(c->data.html.object[i].content,
+ c->url, html_object_callback,
+ c, (void * ) i,
+ 0, 0, false);
}
break;