summaryrefslogtreecommitdiff
path: root/content
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2010-04-05 21:35:38 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2010-04-05 21:35:38 +0000
commit2748fe4f6483f8cfb3c4f91a01e8d897b7d1ac47 (patch)
tree0647010a17aee4237d125e42cc8bd726ec0573ae /content
parent89daef932a9bbc46e276f6d306b0aabf109806f9 (diff)
downloadnetsurf-2748fe4f6483f8cfb3c4f91a01e8d897b7d1ac47.tar.gz
netsurf-2748fe4f6483f8cfb3c4f91a01e8d897b7d1ac47.tar.bz2
Make downloads work again.
svn path=/trunk/netsurf/; revision=10243
Diffstat (limited to 'content')
-rw-r--r--content/content.c25
-rw-r--r--content/content.h9
-rw-r--r--content/hlcache.c52
-rw-r--r--content/hlcache.h10
-rw-r--r--content/llcache.c66
-rw-r--r--content/llcache.h15
6 files changed, 128 insertions, 49 deletions
diff --git a/content/content.c b/content/content.c
index a247dda2b..a44eb2847 100644
--- a/content/content.c
+++ b/content/content.c
@@ -1409,28 +1409,3 @@ nserror content_abort(struct content *c)
return llcache_handle_abort(c->llcache);
}
-/**
- * Convert a content into a download
- *
- * \param h Content to convert
- * \return Pointer to low-level cache handle
- */
-llcache_handle *content_convert_to_download(hlcache_handle *h)
-{
- struct content *c = hlcache_handle_get_content(h);
- llcache_handle *stream = c->llcache;
-
- assert(c != NULL);
- assert(c->status == CONTENT_STATUS_LOADING);
-
- /** \todo Is this safe? */
- c->llcache = NULL;
-
- /** \todo Tell the llcache to stream the data without caching it */
-
- /** \todo Invalidate the content object so it's flushed from the
- * cache at the earliest opportunity */
-
- return stream;
-}
-
diff --git a/content/content.h b/content/content.h
index ef91135ee..b9af6c267 100644
--- a/content/content.h
+++ b/content/content.h
@@ -33,11 +33,10 @@
#include "content/content_type.h"
#include "desktop/plot_style.h"
-struct llcache_handle;
-
struct box;
struct browser_window;
struct content;
+struct llcache_handle;
struct hlcache_handle;
struct object_params;
@@ -63,6 +62,7 @@ typedef enum {
CONTENT_MSG_REFORMAT, /**< content_reformat done */
CONTENT_MSG_REDRAW, /**< needs redraw (eg. new animation frame) */
CONTENT_MSG_REFRESH, /**< wants refresh */
+ CONTENT_MSG_DOWNLOAD /**< download, not for display */
} content_msg;
/** Extra data for some content_msg messages. */
@@ -82,6 +82,8 @@ union content_msg_data {
float object_width, object_height;
} redraw;
int delay; /**< Minimum delay, for CONTENT_MSG_REFRESH */
+ /** Low-level cache handle, for CONTENT_MSG_DOWNLOAD */
+ struct llcache_handle *download;
};
@@ -142,7 +144,4 @@ void content_invalidate_reuse_data(struct hlcache_handle *c);
const char *content_get_refresh_url(struct hlcache_handle *c);
struct bitmap *content_get_bitmap(struct hlcache_handle *c);
-/* Download support */
-struct llcache_handle *content_convert_to_download(struct hlcache_handle *c);
-
#endif
diff --git a/content/hlcache.c b/content/hlcache.c
index 298fe8151..bbe0cd753 100644
--- a/content/hlcache.c
+++ b/content/hlcache.c
@@ -40,6 +40,8 @@ struct hlcache_retrieval_ctx {
hlcache_handle *handle; /**< High-level handle for object */
+ uint32_t flags; /**< Retrieval flags */
+
const content_type *accepted_types; /**< Accepted types, or NULL */
hlcache_child_context child; /**< Child context */
@@ -67,7 +69,8 @@ static hlcache_entry *hlcache_content_list;
static nserror hlcache_llcache_callback(llcache_handle *handle,
const llcache_event *event, void *pw);
static bool hlcache_type_is_acceptable(llcache_handle *llcache,
- const content_type *accepted_types);
+ const content_type *accepted_types,
+ content_type *computed_type);
static nserror hlcache_find_content(hlcache_retrieval_ctx *ctx);
static void hlcache_content_callback(struct content *c,
content_msg msg, union content_msg_data data, void *pw);
@@ -104,6 +107,7 @@ nserror hlcache_handle_retrieve(const char *url, uint32_t flags,
ctx->child.quirks = child->quirks;
}
+ ctx->flags = flags;
ctx->accepted_types = accepted_types;
ctx->handle->cb = cb;
@@ -227,10 +231,28 @@ nserror hlcache_llcache_callback(llcache_handle *handle,
switch (event->type) {
case LLCACHE_EVENT_HAD_HEADERS:
- if (hlcache_type_is_acceptable(handle, ctx->accepted_types)) {
+ {
+ content_type type;
+
+ if (hlcache_type_is_acceptable(handle,
+ ctx->accepted_types, &type)) {
error = hlcache_find_content(ctx);
if (error != NSERROR_OK)
return error;
+ } else if (type == CONTENT_OTHER &&
+ ctx->flags & HLCACHE_RETRIEVE_MAY_DOWNLOAD) {
+ /* Unknown type, and we can download, so convert */
+ llcache_handle_force_stream(handle);
+
+ if (ctx->handle->cb != NULL) {
+ hlcache_event hlevent;
+
+ hlevent.type = CONTENT_MSG_DOWNLOAD;
+ hlevent.data.download = handle;
+
+ ctx->handle->cb(ctx->handle, &hlevent,
+ ctx->handle->pw);
+ }
} else {
/* Unacceptable type: abort fetch and report error */
llcache_handle_abort(handle);
@@ -249,6 +271,7 @@ nserror hlcache_llcache_callback(llcache_handle *handle,
/* No longer require retrieval context */
free(ctx);
+ }
break;
case LLCACHE_EVENT_HAD_DATA:
/* fall through */
@@ -277,19 +300,18 @@ nserror hlcache_llcache_callback(llcache_handle *handle,
*
* \param llcache Low-level cache object to consider
* \param accepted_types Array of acceptable types, or NULL for any
+ * \param computed_type Pointer to location to receive computed type of object
* \return True if the type is acceptable, false otherwise
*/
bool hlcache_type_is_acceptable(llcache_handle *llcache,
- const content_type *accepted_types)
+ const content_type *accepted_types, content_type *computed_type)
{
const char *content_type_header;
char *mime_type;
http_parameter *params;
content_type type;
nserror error;
-
- if (accepted_types == NULL)
- return true;
+ bool acceptable;
content_type_header =
llcache_handle_get_header(llcache, "Content-Type");
@@ -306,14 +328,22 @@ bool hlcache_type_is_acceptable(llcache_handle *llcache,
free(mime_type);
http_parameter_list_destroy(params);
- while (*accepted_types != CONTENT_UNKNOWN) {
- if (*accepted_types == type)
- break;
+ if (accepted_types == NULL) {
+ acceptable = type != CONTENT_OTHER;
+ } else {
+ while (*accepted_types != CONTENT_UNKNOWN) {
+ if (*accepted_types == type)
+ break;
+
+ accepted_types++;
+ }
- accepted_types++;
+ acceptable = *accepted_types == type;
}
- return *accepted_types == type;
+ *computed_type = type;
+
+ return acceptable;
}
/**
diff --git a/content/hlcache.h b/content/hlcache.h
index 1208b15c4..9f03052fa 100644
--- a/content/hlcache.h
+++ b/content/hlcache.h
@@ -53,6 +53,16 @@ typedef struct {
typedef nserror (*hlcache_handle_callback)(hlcache_handle *handle,
const hlcache_event *event, void *pw);
+/** Flags for high-level cache object retrieval */
+enum hlcache_retrieve_flag {
+ /* Note: low-level cache retrieval flags occupy the bottom 16 bits of
+ * the flags word. High-level cache flags occupy the top 16 bits.
+ * To avoid confusion, high-level flags are allocated from bit 31 down.
+ */
+ /** It's permitted to convert this request into a download */
+ HLCACHE_RETRIEVE_MAY_DOWNLOAD = (1 << 31)
+};
+
/**
* Retrieve a high-level cache handle for an object
*
diff --git a/content/llcache.c b/content/llcache.c
index 94df0f6e5..7f44cc916 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -169,6 +169,8 @@ static nserror llcache_object_add_to_list(llcache_object *object,
llcache_object **list);
static nserror llcache_object_remove_from_list(llcache_object *object,
llcache_object **list);
+static bool llcache_object_in_list(const llcache_object *object,
+ const llcache_object *list);
static nserror llcache_object_notify_users(llcache_object *object);
@@ -365,6 +367,28 @@ nserror llcache_handle_abort(llcache_handle *handle)
}
/* See llcache.h for documentation */
+nserror llcache_handle_force_stream(llcache_handle *handle)
+{
+ llcache_object_user *user = (llcache_object_user *) handle;
+ llcache_object *object = handle->object;
+
+ /* Cannot stream if there are multiple users */
+ if (user->prev != NULL || user->next != NULL)
+ return NSERROR_OK;
+
+ /* Forcibly uncache this object */
+ if (llcache_object_in_list(object, llcache_cached_objects)) {
+ llcache_object_remove_from_list(object,
+ &llcache_cached_objects);
+ llcache_object_add_to_list(object, &llcache_uncached_objects);
+ }
+
+ object->fetch.flags |= LLCACHE_RETRIEVE_STREAM_DATA;
+
+ return NSERROR_OK;
+}
+
+/* See llcache.h for documentation */
const char *llcache_handle_get_url(const llcache_handle *handle)
{
return handle->object != NULL ? handle->object->url : NULL;
@@ -1055,6 +1079,26 @@ nserror llcache_object_remove_from_list(llcache_object *object,
}
/**
+ * Determine if a low-level cache object resides in a given list
+ *
+ * \param object Object to search for
+ * \param list List to search in
+ * \return True if object resides in list, false otherwise
+ */
+bool llcache_object_in_list(const llcache_object *object,
+ const llcache_object *list)
+{
+ while (list != NULL) {
+ if (list == object)
+ break;
+
+ list = list->next;
+ }
+
+ return list != NULL;
+}
+
+/**
* Notify users of an object's current state
*
* \param object Object to notify users about
@@ -1139,16 +1183,24 @@ nserror llcache_object_notify_users(llcache_object *object)
if (handle->state == LLCACHE_FETCH_DATA &&
objstate >= LLCACHE_FETCH_DATA &&
object->source_len > handle->bytes) {
- size_t oldbytes = handle->bytes;
+ /* Construct HAD_DATA event */
+ event.type = LLCACHE_EVENT_HAD_DATA;
+ event.data.data.buf =
+ object->source_data + handle->bytes;
+ event.data.data.len =
+ object->source_len - handle->bytes;
/* Update record of last byte emitted */
- handle->bytes = object->source_len;
-
- /* Emit HAD_DATA event */
- event.type = LLCACHE_EVENT_HAD_DATA;
- event.data.data.buf = object->source_data + oldbytes;
- event.data.data.len = object->source_len - oldbytes;
+ if (object->fetch.flags &
+ LLCACHE_RETRIEVE_STREAM_DATA) {
+ /* Streaming, so reset to zero to
+ * minimise amount of cached source data */
+ handle->bytes = object->source_len = 0;
+ } else {
+ handle->bytes = object->source_len;
+ }
+ /* Emit event */
error = handle->cb(handle, &event, handle->pw);
if (error != NSERROR_OK) {
user->iterator_target = false;
diff --git a/content/llcache.h b/content/llcache.h
index 434d0b641..3c965d3dc 100644
--- a/content/llcache.h
+++ b/content/llcache.h
@@ -82,6 +82,9 @@ typedef nserror (*llcache_handle_callback)(llcache_handle *handle,
/** Flags for low-level cache object retrieval */
enum llcache_retrieve_flag {
+ /* Note: We're permitted a maximum of 16 flags which must reside in the
+ * bottom 16 bits of the flags word. See hlcache.h for further details.
+ */
/** Force a new fetch */
LLCACHE_RETRIEVE_FORCE_FETCH = (1 << 0),
/** Requested URL was verified */
@@ -89,7 +92,9 @@ enum llcache_retrieve_flag {
/** Permit content-type sniffing */
LLCACHE_RETRIEVE_SNIFF_TYPE = (1 << 2),
/**< No error pages */
- LLCACHE_RETRIEVE_NO_ERROR_PAGES = (1 << 3)
+ LLCACHE_RETRIEVE_NO_ERROR_PAGES = (1 << 3),
+ /**< Stream data (implies that object is not cacheable) */
+ LLCACHE_RETRIEVE_STREAM_DATA = (1 << 4)
};
/** Low-level cache query types */
@@ -219,6 +224,14 @@ nserror llcache_handle_clone(llcache_handle *handle, llcache_handle **result);
nserror llcache_handle_abort(llcache_handle *handle);
/**
+ * Force a low-level cache handle into streaming mode
+ *
+ * \param handle Handle to stream
+ * \return NSERROR_OK on success, appropriate error otherwise
+ */
+nserror llcache_handle_force_stream(llcache_handle *handle);
+
+/**
* Retrieve the post-redirect URL of a low-level cache object
*
* \param handle Handle to retrieve URL from