mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-22 04:02:34 +03:00
Make downloads work again.
svn path=/trunk/netsurf/; revision=10243
This commit is contained in:
parent
89daef932a
commit
2748fe4f64
@ -33,8 +33,8 @@ S_PDF := $(addprefix desktop/save_pdf/,$(S_PDF))
|
||||
|
||||
# S_BROWSER are sources related to full browsers but are common
|
||||
# between RISC OS, GTK, BeOS and AmigaOS builds
|
||||
S_BROWSER := browser.c frames.c history_core.c netsurf.c save_complete.c \
|
||||
save_text.c selection.c textinput.c
|
||||
S_BROWSER := browser.c download.c frames.c history_core.c netsurf.c \
|
||||
save_complete.c save_text.c selection.c textinput.c
|
||||
S_BROWSER := $(addprefix desktop/,$(S_BROWSER))
|
||||
|
||||
# S_RISCOS are sources purely for the RISC OS build
|
||||
|
@ -37,11 +37,11 @@
|
||||
#include "amiga/iff_dr2d.h"
|
||||
#include "amiga/theme.h"
|
||||
|
||||
#include "content/fetch.h"
|
||||
|
||||
#include "desktop/download.h"
|
||||
#include "desktop/selection.h"
|
||||
#include "desktop/save_complete.h"
|
||||
|
||||
#include "utils/errors.h"
|
||||
#include "utils/messages.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
@ -55,10 +55,12 @@
|
||||
|
||||
#include <reaction/reaction_macros.h>
|
||||
|
||||
struct gui_download_window *gui_download_window_create(const char *url,
|
||||
const char *mime_type, struct fetch *fetch,
|
||||
unsigned int total_size, struct gui_window *gui)
|
||||
struct gui_download_window *gui_download_window_create(download_context *ctx,
|
||||
struct gui_window *gui)
|
||||
{
|
||||
const char *url = download_context_get_url(ctx);
|
||||
const char *mime_type = download_context_get_mime_type(ctx);
|
||||
unsigned long total_size = download_context_get_total_length(ctx);
|
||||
struct gui_download_window *dw;
|
||||
APTR va[3];
|
||||
|
||||
@ -139,18 +141,18 @@ struct gui_download_window *gui_download_window_create(const char *url,
|
||||
EndWindow;
|
||||
|
||||
dw->win = (struct Window *)RA_OpenWindow(dw->objects[OID_MAIN]);
|
||||
dw->fetch = fetch;
|
||||
dw->ctx = ctx;
|
||||
|
||||
dw->node = AddObject(window_list,AMINS_DLWINDOW);
|
||||
dw->node->objstruct = dw;
|
||||
return dw;
|
||||
}
|
||||
|
||||
void gui_download_window_data(struct gui_download_window *dw, const char *data,
|
||||
unsigned int size)
|
||||
nserror gui_download_window_data(struct gui_download_window *dw,
|
||||
const char *data, unsigned int size)
|
||||
{
|
||||
APTR va[3];
|
||||
if(!dw) return;
|
||||
if(!dw) return NSERROR_SAVE_FAILED;
|
||||
|
||||
FWrite(dw->fh,data,1,size);
|
||||
|
||||
@ -176,6 +178,8 @@ void gui_download_window_data(struct gui_download_window *dw, const char *data,
|
||||
FUELGAUGE_VarArgs,va,
|
||||
TAG_DONE);
|
||||
}
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
void gui_download_window_error(struct gui_download_window *dw,
|
||||
@ -187,7 +191,7 @@ void gui_download_window_error(struct gui_download_window *dw,
|
||||
|
||||
void ami_download_window_abort(struct gui_download_window *dw)
|
||||
{
|
||||
fetch_abort(dw->fetch);
|
||||
download_context_abort(dw->ctx);
|
||||
gui_download_window_done(dw);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
#define AMIGA_DOWNLOAD_H
|
||||
#include "amiga/gui.h"
|
||||
|
||||
struct download_context;
|
||||
|
||||
struct dlnode
|
||||
{
|
||||
struct Node node;
|
||||
@ -36,7 +38,7 @@ struct gui_download_window {
|
||||
uint32 downloaded;
|
||||
struct dlnode *dln;
|
||||
struct browser_window *bw;
|
||||
struct fetch *fetch;
|
||||
struct download_context *ctx;
|
||||
char *url;
|
||||
char fname[1024];
|
||||
};
|
||||
|
@ -778,17 +778,17 @@ void gui_quit(void)
|
||||
|
||||
|
||||
|
||||
struct gui_download_window *gui_download_window_create(const char *url,
|
||||
const char *mime_type, struct fetch *fetch,
|
||||
unsigned int total_size, struct gui_window *gui)
|
||||
struct gui_download_window *gui_download_window_create(download_context *ctx,
|
||||
struct gui_window *gui)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void gui_download_window_data(struct gui_download_window *dw, const char *data,
|
||||
unsigned int size)
|
||||
nserror gui_download_window_data(struct gui_download_window *dw,
|
||||
const char *data, unsigned int size)
|
||||
{
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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);
|
||||
|
||||
@ -364,6 +366,28 @@ nserror llcache_handle_abort(llcache_handle *handle)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@ -1054,6 +1078,26 @@ nserror llcache_object_remove_from_list(llcache_object *object,
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@ -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;
|
||||
|
@ -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 */
|
||||
@ -218,6 +223,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
|
||||
*
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "css/css.h"
|
||||
#include "desktop/401login.h"
|
||||
#include "desktop/browser.h"
|
||||
#include "desktop/download.h"
|
||||
#include "desktop/frames.h"
|
||||
#include "desktop/history_core.h"
|
||||
#include "desktop/gui.h"
|
||||
@ -81,7 +82,8 @@ static nserror browser_window_callback(hlcache_handle *c,
|
||||
const hlcache_event *event, void *pw);
|
||||
static void browser_window_refresh(void *p);
|
||||
static bool browser_window_check_throbber(struct browser_window *bw);
|
||||
static void browser_window_convert_to_download(struct browser_window *bw);
|
||||
static void browser_window_convert_to_download(struct browser_window *bw,
|
||||
llcache_handle *stream);
|
||||
static void browser_window_start_throbber(struct browser_window *bw);
|
||||
static void browser_window_stop_throbber(struct browser_window *bw);
|
||||
static void browser_window_set_icon(struct browser_window *bw);
|
||||
@ -89,8 +91,6 @@ static void browser_window_set_status(struct browser_window *bw,
|
||||
const char *text);
|
||||
static void browser_window_set_pointer(struct gui_window *g,
|
||||
gui_pointer_shape shape);
|
||||
static nserror download_window_callback(llcache_handle *handle,
|
||||
const llcache_event *event, void *pw);
|
||||
static void browser_window_destroy_children(struct browser_window *bw);
|
||||
static void browser_window_destroy_internal(struct browser_window *bw);
|
||||
static void browser_window_set_scale_internal(struct browser_window *bw,
|
||||
@ -338,15 +338,24 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
|
||||
if (download) {
|
||||
llcache_handle *l;
|
||||
|
||||
error = llcache_handle_retrieve(url2,
|
||||
fetch_flags | LLCACHE_RETRIEVE_FORCE_FETCH,
|
||||
referer, fetch_is_post ? &post : NULL,
|
||||
download_window_callback, NULL, &l);
|
||||
fetch_flags |= LLCACHE_RETRIEVE_FORCE_FETCH;
|
||||
fetch_flags |= LLCACHE_RETRIEVE_STREAM_DATA;
|
||||
|
||||
error = llcache_handle_retrieve(url2, fetch_flags, referer,
|
||||
fetch_is_post ? &post : NULL,
|
||||
NULL, NULL, &l);
|
||||
if (error != NSERROR_OK)
|
||||
LOG(("Failed to fetch download: %d", error));
|
||||
|
||||
free(url2);
|
||||
|
||||
error = download_context_create(l, bw->window);
|
||||
if (error != NSERROR_OK) {
|
||||
LOG(("Failed creating download context: %d", error));
|
||||
llcache_handle_abort(l);
|
||||
llcache_handle_release(l);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -406,7 +415,9 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
|
||||
browser_window_set_status(bw, messages_get("Loading"));
|
||||
bw->history_add = add_to_history;
|
||||
|
||||
error = hlcache_handle_retrieve(url2, 0, referer,
|
||||
error = hlcache_handle_retrieve(url2,
|
||||
fetch_flags | HLCACHE_RETRIEVE_MAY_DOWNLOAD,
|
||||
referer,
|
||||
fetch_is_post ? &post : NULL,
|
||||
browser_window_callback, bw,
|
||||
parent != NULL ? &child : NULL,
|
||||
@ -439,21 +450,26 @@ nserror browser_window_callback(hlcache_handle *c,
|
||||
struct browser_window *bw = pw;
|
||||
|
||||
switch (event->type) {
|
||||
case CONTENT_MSG_DOWNLOAD:
|
||||
assert(bw->loading_content == c);
|
||||
|
||||
browser_window_convert_to_download(bw, event->data.download);
|
||||
|
||||
break;
|
||||
|
||||
case CONTENT_MSG_LOADING:
|
||||
assert(bw->loading_content == c);
|
||||
|
||||
if (content_get_type(c) == CONTENT_OTHER)
|
||||
browser_window_convert_to_download(bw);
|
||||
#ifdef WITH_THEME_INSTALL
|
||||
else if (content_get_type(c) == CONTENT_THEME) {
|
||||
if (content_get_type(c) == CONTENT_THEME) {
|
||||
theme_install_start(c);
|
||||
bw->loading_content = NULL;
|
||||
//newcache do we not just pass ownership to the theme installation stuff?
|
||||
hlcache_handle_release(c);
|
||||
browser_window_stop_throbber(bw);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
else {
|
||||
{
|
||||
bw->refresh_interval = -1;
|
||||
browser_window_set_status(bw,
|
||||
content_get_status_message(c));
|
||||
@ -612,24 +628,18 @@ nserror browser_window_callback(hlcache_handle *c,
|
||||
* Transfer the loading_content to a new download window.
|
||||
*/
|
||||
|
||||
void browser_window_convert_to_download(struct browser_window *bw)
|
||||
void browser_window_convert_to_download(struct browser_window *bw,
|
||||
llcache_handle *stream)
|
||||
{
|
||||
struct gui_download_window *download_window;
|
||||
hlcache_handle *c = bw->loading_content;
|
||||
llcache_handle *stream;
|
||||
nserror error;
|
||||
|
||||
assert(c);
|
||||
error = download_context_create(stream, bw->window);
|
||||
if (error != NSERROR_OK) {
|
||||
llcache_handle_abort(stream);
|
||||
llcache_handle_release(stream);
|
||||
|
||||
stream = content_convert_to_download(c);
|
||||
|
||||
/** \todo Sort parameters out here */
|
||||
download_window = gui_download_window_create(
|
||||
llcache_handle_get_url(stream),
|
||||
llcache_handle_get_header(stream, "Content-Type"),
|
||||
NULL, 0, NULL);
|
||||
|
||||
llcache_handle_change_callback(stream,
|
||||
download_window_callback, download_window);
|
||||
return;
|
||||
}
|
||||
|
||||
/* remove content from browser window */
|
||||
hlcache_handle_release(bw->loading_content);
|
||||
@ -1340,64 +1350,6 @@ void browser_window_find_target_internal(struct browser_window *bw,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback for fetch for download window fetches.
|
||||
*/
|
||||
|
||||
nserror download_window_callback(llcache_handle *handle,
|
||||
const llcache_event *event, void *pw)
|
||||
{
|
||||
struct gui_download_window *download_window = pw;
|
||||
|
||||
switch (event->type) {
|
||||
case LLCACHE_EVENT_HAD_HEADERS:
|
||||
assert(download_window == NULL);
|
||||
|
||||
/** \todo Ensure parameters are correct here */
|
||||
download_window = gui_download_window_create(
|
||||
llcache_handle_get_url(handle),
|
||||
llcache_handle_get_header(handle,
|
||||
"Content-Type"),
|
||||
NULL, 0, NULL);
|
||||
if (download_window == NULL)
|
||||
return NSERROR_NOMEM;
|
||||
|
||||
llcache_handle_change_callback(handle,
|
||||
download_window_callback, download_window);
|
||||
break;
|
||||
|
||||
case LLCACHE_EVENT_HAD_DATA:
|
||||
assert(download_window != NULL);
|
||||
|
||||
/** \todo Lose ugly cast */
|
||||
gui_download_window_data(download_window,
|
||||
(char *) event->data.data.buf,
|
||||
event->data.data.len);
|
||||
|
||||
break;
|
||||
|
||||
case LLCACHE_EVENT_DONE:
|
||||
assert(download_window != NULL);
|
||||
|
||||
gui_download_window_done(download_window);
|
||||
|
||||
break;
|
||||
|
||||
case LLCACHE_EVENT_ERROR:
|
||||
if (download_window != NULL)
|
||||
gui_download_window_error(download_window,
|
||||
event->data.msg);
|
||||
|
||||
break;
|
||||
|
||||
case LLCACHE_EVENT_PROGRESS:
|
||||
break;
|
||||
}
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle mouse clicks in a browser window.
|
||||
*
|
||||
|
215
desktop/download.c
Normal file
215
desktop/download.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
|
||||
*
|
||||
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
||||
*
|
||||
* NetSurf is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* NetSurf is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file Core download context (implementation)
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "content/llcache.h"
|
||||
#include "desktop/download.h"
|
||||
#include "desktop/gui.h"
|
||||
#include "utils/http.h"
|
||||
|
||||
/**
|
||||
* A context for a download
|
||||
*/
|
||||
struct download_context {
|
||||
llcache_handle *llcache; /**< Low-level cache handle */
|
||||
struct gui_window *parent; /**< Parent window */
|
||||
|
||||
char *mime_type; /**< MIME type of download */
|
||||
unsigned long total_length; /**< Length of data, in bytes */
|
||||
|
||||
struct gui_download_window *window; /**< GUI download window */
|
||||
};
|
||||
|
||||
/**
|
||||
* Process fetch headers for a download context.
|
||||
* Extracts MIME type, total length, and creates gui_download_window
|
||||
*
|
||||
* \param ctx Context to process
|
||||
* \return NSERROR_OK on success, appropriate error otherwise
|
||||
*/
|
||||
static nserror download_context_process_headers(download_context *ctx)
|
||||
{
|
||||
const char *http_header;
|
||||
char *mime_type;
|
||||
http_parameter *params;
|
||||
unsigned long length;
|
||||
nserror error;
|
||||
|
||||
/* Retrieve and parse Content-Type */
|
||||
http_header = llcache_handle_get_header(ctx->llcache, "Content-Type");
|
||||
if (http_header == NULL)
|
||||
http_header = "text/plain";
|
||||
|
||||
error = http_parse_content_type(http_header, &mime_type, ¶ms);
|
||||
if (error != NSERROR_OK)
|
||||
return error;
|
||||
|
||||
/* Don't care about parameters */
|
||||
http_parameter_list_destroy(params);
|
||||
|
||||
/* Retrieve and parse Content-Length */
|
||||
http_header = llcache_handle_get_header(ctx->llcache, "Content-Length");
|
||||
if (http_header == NULL)
|
||||
length = 0;
|
||||
else
|
||||
length = strtoul(http_header, NULL, 10);
|
||||
|
||||
ctx->mime_type = mime_type;
|
||||
ctx->total_length = length;
|
||||
|
||||
/* Create the frontend window */
|
||||
ctx->window = gui_download_window_create(ctx, ctx->parent);
|
||||
if (ctx->window == NULL) {
|
||||
free(ctx->mime_type);
|
||||
ctx->mime_type = NULL;
|
||||
return NSERROR_NOMEM;
|
||||
}
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for low-level cache events
|
||||
*
|
||||
* \param handle Low-level cache handle
|
||||
* \param event Event object
|
||||
* \param pw Our context
|
||||
* \return NSERROR_OK on success, appropriate error otherwise
|
||||
*/
|
||||
static nserror download_callback(llcache_handle *handle,
|
||||
const llcache_event *event, void *pw)
|
||||
{
|
||||
download_context *ctx = pw;
|
||||
nserror error = NSERROR_OK;
|
||||
|
||||
switch (event->type) {
|
||||
case LLCACHE_EVENT_HAD_HEADERS:
|
||||
error = download_context_process_headers(ctx);
|
||||
if (error != NSERROR_OK) {
|
||||
llcache_handle_abort(handle);
|
||||
download_context_destroy(ctx);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LLCACHE_EVENT_HAD_DATA:
|
||||
/* If we didn't know up-front that this fetch was for download,
|
||||
* then we won't receive the HAD_HEADERS event. Catch up now.
|
||||
*/
|
||||
if (ctx->window == NULL) {
|
||||
error = download_context_process_headers(ctx);
|
||||
if (error != NSERROR_OK) {
|
||||
llcache_handle_abort(handle);
|
||||
download_context_destroy(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if (error == NSERROR_OK) {
|
||||
/** \todo Lose ugly cast */
|
||||
error = gui_download_window_data(ctx->window,
|
||||
(char *) event->data.data.buf,
|
||||
event->data.data.len);
|
||||
if (error != NSERROR_OK)
|
||||
llcache_handle_abort(handle);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LLCACHE_EVENT_DONE:
|
||||
assert(ctx->window != NULL);
|
||||
|
||||
gui_download_window_done(ctx->window);
|
||||
|
||||
break;
|
||||
|
||||
case LLCACHE_EVENT_ERROR:
|
||||
if (ctx->window != NULL)
|
||||
gui_download_window_error(ctx->window, event->data.msg);
|
||||
|
||||
break;
|
||||
|
||||
case LLCACHE_EVENT_PROGRESS:
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* See download.h for documentation */
|
||||
nserror download_context_create(llcache_handle *llcache,
|
||||
struct gui_window *parent)
|
||||
{
|
||||
download_context *ctx;
|
||||
|
||||
ctx = malloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NSERROR_NOMEM;
|
||||
|
||||
ctx->llcache = llcache;
|
||||
ctx->parent = parent;
|
||||
ctx->mime_type = NULL;
|
||||
ctx->total_length = 0;
|
||||
ctx->window = NULL;
|
||||
|
||||
llcache_handle_change_callback(llcache, download_callback, ctx);
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
/* See download.h for documentation */
|
||||
void download_context_destroy(download_context *ctx)
|
||||
{
|
||||
llcache_handle_release(ctx->llcache);
|
||||
|
||||
free(ctx->mime_type);
|
||||
|
||||
/* Window is not owned by us, so don't attempt to destroy it */
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/* See download.h for documentation */
|
||||
void download_context_abort(download_context *ctx)
|
||||
{
|
||||
llcache_handle_abort(ctx->llcache);
|
||||
}
|
||||
|
||||
/* See download.h for documentation */
|
||||
const char *download_context_get_url(const download_context *ctx)
|
||||
{
|
||||
return llcache_handle_get_url(ctx->llcache);
|
||||
}
|
||||
|
||||
/* See download.h for documentation */
|
||||
const char *download_context_get_mime_type(const download_context *ctx)
|
||||
{
|
||||
return ctx->mime_type;
|
||||
}
|
||||
|
||||
/* See download.h for documentation */
|
||||
unsigned long download_context_get_total_length(const download_context *ctx)
|
||||
{
|
||||
return ctx->total_length;
|
||||
}
|
||||
|
90
desktop/download.h
Normal file
90
desktop/download.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
|
||||
*
|
||||
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
||||
*
|
||||
* NetSurf is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* NetSurf is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file Core download context (interface)
|
||||
*/
|
||||
|
||||
#ifndef NETSURF_DESKTOP_DOWNLOAD_H_
|
||||
#define NETSURF_DESKTOP_DOWNLOAD_H_
|
||||
|
||||
#include "utils/errors.h"
|
||||
|
||||
struct gui_window;
|
||||
struct llcache_handle;
|
||||
|
||||
/** Type of a download context */
|
||||
typedef struct download_context download_context;
|
||||
|
||||
/**
|
||||
* Create a download context
|
||||
*
|
||||
* \param llcache Low-level cache handle for download
|
||||
* \param parent Parent window, for UI
|
||||
* \return NSERROR_OK on success, appropriate error otherwise
|
||||
*
|
||||
* This must only be called by the core browser window fetch infrastructure.
|
||||
* Ownership of the download context object created is passed to the frontend.
|
||||
*/
|
||||
nserror download_context_create(struct llcache_handle *llcache,
|
||||
struct gui_window *parent);
|
||||
|
||||
/**
|
||||
* Destroy a download context
|
||||
*
|
||||
* \param ctx Context to destroy
|
||||
*
|
||||
* Called by the frontend when it has finished with a download context
|
||||
*/
|
||||
void download_context_destroy(download_context *ctx);
|
||||
|
||||
/**
|
||||
* Abort a download fetch
|
||||
*
|
||||
* \param ctx Context to abort
|
||||
*
|
||||
* Called by the frontend to abort a download.
|
||||
* The context must be destroyed independently.
|
||||
*/
|
||||
void download_context_abort(download_context *ctx);
|
||||
|
||||
/**
|
||||
* Retrieve the URL for a download
|
||||
*
|
||||
* \param ctx Context to retrieve URL from
|
||||
* \return URL string
|
||||
*/
|
||||
const char *download_context_get_url(const download_context *ctx);
|
||||
|
||||
/**
|
||||
* Retrieve the MIME type for a download
|
||||
*
|
||||
* \param ctx Context to retrieve MIME type from
|
||||
* \return MIME type string
|
||||
*/
|
||||
const char *download_context_get_mime_type(const download_context *ctx);
|
||||
|
||||
/**
|
||||
* Retrieve total byte length of download
|
||||
*
|
||||
* \param ctx Context to retrieve byte length from
|
||||
* \return Total length, in bytes, or 0 if unknown
|
||||
*/
|
||||
unsigned long download_context_get_total_length(const download_context *ctx);
|
||||
|
||||
#endif
|
@ -41,7 +41,6 @@ typedef enum {
|
||||
GUI_SAVE_CLIPBOARD_CONTENTS
|
||||
} gui_save_type;
|
||||
|
||||
struct fetch;
|
||||
struct gui_window;
|
||||
struct gui_download_window;
|
||||
|
||||
@ -58,7 +57,9 @@ typedef enum { GUI_POINTER_DEFAULT, GUI_POINTER_POINT, GUI_POINTER_CARET,
|
||||
#include "content/content.h"
|
||||
#include "content/hlcache.h"
|
||||
#include "desktop/browser.h"
|
||||
#include "desktop/download.h"
|
||||
#include "desktop/search.h"
|
||||
#include "utils/errors.h"
|
||||
|
||||
void gui_stdout(void);
|
||||
void gui_multitask(void);
|
||||
@ -102,11 +103,10 @@ void gui_window_save_link(struct gui_window *g, const char *url,
|
||||
const char *title);
|
||||
void gui_window_set_scale(struct gui_window *g, float scale);
|
||||
|
||||
struct gui_download_window *gui_download_window_create(const char *url,
|
||||
const char *mime_type, struct fetch *fetch,
|
||||
unsigned int total_size, struct gui_window *gui);
|
||||
void gui_download_window_data(struct gui_download_window *dw, const char *data,
|
||||
unsigned int size);
|
||||
struct gui_download_window *gui_download_window_create(download_context *ctx,
|
||||
struct gui_window *parent);
|
||||
nserror gui_download_window_data(struct gui_download_window *dw,
|
||||
const char *data, unsigned int size);
|
||||
void gui_download_window_error(struct gui_download_window *dw,
|
||||
const char *error_msg);
|
||||
void gui_download_window_done(struct gui_download_window *dw);
|
||||
|
@ -1358,16 +1358,16 @@ gui_window_set_search_ico(hlcache_handle *ico)
|
||||
{
|
||||
}
|
||||
|
||||
struct gui_download_window *gui_download_window_create(const char *url,
|
||||
const char *mime_type, struct fetch *fetch,
|
||||
unsigned int total_size, struct gui_window *gui)
|
||||
struct gui_download_window *gui_download_window_create(download_context *ctx,
|
||||
struct gui_window *parent)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void gui_download_window_data(struct gui_download_window *dw, const char *data,
|
||||
unsigned int size)
|
||||
nserror gui_download_window_data(struct gui_download_window *dw,
|
||||
const char *data, unsigned int size)
|
||||
{
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
void gui_download_window_error(struct gui_download_window *dw,
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "utils/utils.h"
|
||||
#include "utils/url.h"
|
||||
#include "utils/messages.h"
|
||||
#include "content/fetch.h"
|
||||
#include "desktop/gui.h"
|
||||
#include "gtk/gtk_gui.h"
|
||||
#include "gtk/gtk_scaffolding.h"
|
||||
@ -195,10 +194,11 @@ gboolean nsgtk_download_hide (GtkWidget *window)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct gui_download_window *gui_download_window_create(const char *url,
|
||||
const char *mime_type, struct fetch *fetch,
|
||||
unsigned int total_size, struct gui_window *gui)
|
||||
struct gui_download_window *gui_download_window_create(download_context *ctx,
|
||||
struct gui_window *gui)
|
||||
{
|
||||
const char *url = download_context_get_url(ctx);
|
||||
unsigned long total_size = download_context_get_total_length(ctx);
|
||||
gchar *domain;
|
||||
gchar *filename;
|
||||
gchar *destination;
|
||||
@ -207,28 +207,48 @@ struct gui_download_window *gui_download_window_create(const char *url,
|
||||
messages_get("gtkUnknownSize") :
|
||||
human_friendly_bytesize(total_size));
|
||||
|
||||
nsgtk_download_parent = nsgtk_scaffolding_window(nsgtk_get_scaffold(
|
||||
gui));
|
||||
nsgtk_download_parent =
|
||||
nsgtk_scaffolding_window(nsgtk_get_scaffold(gui));
|
||||
|
||||
struct gui_download_window *download = malloc(sizeof *download);
|
||||
if (download == NULL)
|
||||
return NULL;
|
||||
|
||||
if (url_nice(url, &filename, false) != URL_FUNC_OK)
|
||||
strcpy(filename, messages_get("gtkUnknownFile"));
|
||||
if (url_host(url, &domain) != URL_FUNC_OK)
|
||||
strcpy(domain, messages_get("gtkUnknownHost"));
|
||||
if (url_nice(url, &filename, false) != URL_FUNC_OK) {
|
||||
filename = g_strdup(messages_get("gtkUnknownFile"));
|
||||
if (filename == NULL) {
|
||||
free(download);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (url_host(url, &domain) != URL_FUNC_OK) {
|
||||
domain = g_strdup(messages_get("gtkUnknownHost"));
|
||||
if (domain == NULL) {
|
||||
g_free(filename);
|
||||
free(download);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
destination = nsgtk_download_dialog_show(filename, domain, size);
|
||||
if (destination == NULL)
|
||||
if (destination == NULL) {
|
||||
g_free(domain);
|
||||
g_free(filename);
|
||||
free(download);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add the new row and store the reference to it (which keeps track of
|
||||
* the tree changes) */
|
||||
gtk_list_store_prepend(nsgtk_download_store, &nsgtk_download_iter);
|
||||
download->row = gtk_tree_row_reference_new(
|
||||
GTK_TREE_MODEL(nsgtk_download_store),
|
||||
gtk_tree_model_get_path(GTK_TREE_MODEL
|
||||
(nsgtk_download_store), &nsgtk_download_iter));
|
||||
gtk_tree_model_get_path(
|
||||
GTK_TREE_MODEL(nsgtk_download_store),
|
||||
&nsgtk_download_iter));
|
||||
|
||||
download->fetch = fetch;
|
||||
download->ctx = ctx;
|
||||
download->name = g_string_new(filename);
|
||||
download->time_left = g_string_new("");
|
||||
download->size_total = total_size;
|
||||
@ -240,38 +260,39 @@ struct gui_download_window *gui_download_window_create(const char *url,
|
||||
download->filename = destination;
|
||||
download->progress = 0;
|
||||
download->error = NULL;
|
||||
download->write = g_io_channel_new_file(destination, "w",
|
||||
&download->error);
|
||||
download->write =
|
||||
g_io_channel_new_file(destination, "w", &download->error);
|
||||
|
||||
if (nsgtk_download_handle_error(download->error)) {
|
||||
g_string_free(download->name, TRUE);
|
||||
g_string_free(download->time_left, TRUE);
|
||||
g_free(download->filename);
|
||||
g_string_free(download->name, TRUE);
|
||||
g_string_free(download->time_left, TRUE);
|
||||
g_free(download->filename);
|
||||
free(download);
|
||||
return NULL;
|
||||
}
|
||||
g_io_channel_set_encoding(download->write, NULL,
|
||||
&download->error);
|
||||
|
||||
g_io_channel_set_encoding(download->write, NULL, &download->error);
|
||||
|
||||
nsgtk_download_change_sensitivity(download, NSGTK_DOWNLOAD_CANCEL);
|
||||
|
||||
nsgtk_download_store_create_item(download);
|
||||
nsgtk_download_show(nsgtk_download_parent);
|
||||
|
||||
if (unknown_size)
|
||||
nsgtk_download_change_status(download,
|
||||
NSGTK_DOWNLOAD_WORKING);
|
||||
nsgtk_download_change_status(download, NSGTK_DOWNLOAD_WORKING);
|
||||
|
||||
if (nsgtk_downloads_num_active == 0)
|
||||
g_timeout_add(UPDATE_RATE, (GSourceFunc)nsgtk_download_update,
|
||||
FALSE);
|
||||
if (nsgtk_downloads_num_active == 0) {
|
||||
g_timeout_add(UPDATE_RATE,
|
||||
(GSourceFunc) nsgtk_download_update, FALSE);
|
||||
}
|
||||
|
||||
nsgtk_downloads_list = g_list_prepend(nsgtk_downloads_list, download);
|
||||
|
||||
return download;
|
||||
}
|
||||
|
||||
|
||||
void gui_download_window_data(struct gui_download_window *dw, const char *data,
|
||||
unsigned int size)
|
||||
nserror gui_download_window_data(struct gui_download_window *dw,
|
||||
const char *data, unsigned int size)
|
||||
{
|
||||
g_io_channel_write_chars(dw->write, data, size, NULL, &dw->error);
|
||||
if (dw->error != NULL) {
|
||||
@ -282,12 +303,14 @@ void gui_download_window_data(struct gui_download_window *dw, const char *data,
|
||||
nsgtk_download_change_status(dw, NSGTK_DOWNLOAD_ERROR);
|
||||
|
||||
nsgtk_download_update(TRUE);
|
||||
fetch_abort(dw->fetch);
|
||||
|
||||
gtk_window_present(nsgtk_download_window);
|
||||
return;
|
||||
|
||||
return NSERROR_SAVE_FAILED;
|
||||
}
|
||||
dw->size_downloaded += size;
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -532,9 +555,11 @@ void nsgtk_download_store_clear_item (struct gui_download_window *dl)
|
||||
gtk_tree_row_reference_get_path(dl->row));
|
||||
gtk_list_store_remove(nsgtk_download_store,
|
||||
&nsgtk_download_iter);
|
||||
g_string_free(dl->name, TRUE);
|
||||
g_string_free(dl->time_left, TRUE);
|
||||
g_free(dl->filename);
|
||||
|
||||
download_context_destroy(dl->ctx);
|
||||
g_string_free(dl->name, TRUE);
|
||||
g_string_free(dl->time_left, TRUE);
|
||||
g_free(dl->filename);
|
||||
g_free(dl);
|
||||
|
||||
nsgtk_download_sensitivity_evaluate(nsgtk_download_selection);
|
||||
@ -551,9 +576,8 @@ void nsgtk_download_store_cancel_item (struct gui_download_window *dl)
|
||||
dl->time_remaining = -1;
|
||||
nsgtk_download_change_sensitivity(dl, NSGTK_DOWNLOAD_CLEAR);
|
||||
nsgtk_download_change_status(dl, NSGTK_DOWNLOAD_CANCELED);
|
||||
|
||||
if (dl->fetch)
|
||||
fetch_abort(dl->fetch);
|
||||
|
||||
download_context_abort(dl->ctx);
|
||||
|
||||
g_unlink(dl->filename);
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
struct download_context;
|
||||
|
||||
enum {
|
||||
NSGTK_DOWNLOAD_PROGRESS,
|
||||
NSGTK_DOWNLOAD_INFO,
|
||||
@ -49,7 +51,7 @@ typedef enum {
|
||||
} nsgtk_download_actions;
|
||||
|
||||
struct gui_download_window {
|
||||
struct fetch *fetch;
|
||||
struct download_context *ctx;
|
||||
nsgtk_download_actions sensitivity;
|
||||
nsgtk_download_status status;
|
||||
|
||||
|
@ -34,6 +34,8 @@ typedef enum {
|
||||
NSERROR_NO_FETCH_HANDLER, /**< No fetch handler for URL scheme */
|
||||
|
||||
NSERROR_NOT_FOUND, /**< Requested item not found */
|
||||
|
||||
NSERROR_SAVE_FAILED /**< Failed to save data */
|
||||
} nserror;
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user