Ejemplo n.º 1
0
/**
 * 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;
}
Ejemplo n.º 2
0
/* See hlcache.h for documentation */
nserror hlcache_handle_abort(hlcache_handle *handle)
{
	struct hlcache_entry *entry = handle->entry;
	struct content *c;

	if (entry == NULL) {
		/* This handle is not yet associated with a cache entry.
		 * The implication is that the fetch for the handle has
		 * not progressed to the point where the entry can be
		 * created. */

		RING_ITERATE_START(struct hlcache_retrieval_ctx,
				   hlcache->retrieval_ctx_ring,
				   ictx) {
			if (ictx->handle == handle &&
					ictx->migrate_target == false) {
				/* This is the nascent context for us,
				 * so abort the fetch */
				llcache_handle_abort(ictx->llcache);
				llcache_handle_release(ictx->llcache);
				/* Remove us from the ring */
				RING_REMOVE(hlcache->retrieval_ctx_ring, ictx);
				/* Throw us away */
				free((char *) ictx->child.charset);
				free(ictx);
				/* And stop */
				RING_ITERATE_STOP(hlcache->retrieval_ctx_ring,
						ictx);
			}
		} RING_ITERATE_END(hlcache->retrieval_ctx_ring, ictx);

		return NSERROR_OK;
	}
Ejemplo n.º 3
0
/* See hlcache.h for documentation */
nserror hlcache_handle_release(hlcache_handle *handle)
{
	if (handle->entry != NULL) {
		content_remove_user(handle->entry->content,
				hlcache_content_callback, handle);
	} else {
		RING_ITERATE_START(struct hlcache_retrieval_ctx,
				   hlcache->retrieval_ctx_ring,
				   ictx) {
			if (ictx->handle == handle &&
					ictx->migrate_target == false) {
				/* This is the nascent context for us,
				 * so abort the fetch */
				llcache_handle_abort(ictx->llcache);
				llcache_handle_release(ictx->llcache);
				/* Remove us from the ring */
				RING_REMOVE(hlcache->retrieval_ctx_ring, ictx);
				/* Throw us away */
				free((char *) ictx->child.charset);
				free(ictx);
				/* And stop */
				RING_ITERATE_STOP(hlcache->retrieval_ctx_ring,
						ictx);
			}
		} RING_ITERATE_END(hlcache->retrieval_ctx_ring, ictx);
	}

	handle->cb = NULL;
	handle->pw = NULL;

	free(handle);

	return NSERROR_OK;
}
Ejemplo n.º 4
0
/**
 * Handler for low-level cache events
 *
 * \param llcache  Low-level cache handle
 * \param event	   Event details
 * \param pw	   Pointer to our context
 * \return NSERROR_OK on success, appropriate error otherwise
 */
nserror content_llcache_callback(llcache_handle *llcache,
		const llcache_event *event, void *pw)
{
	struct content *c = pw;
	union content_msg_data msg_data;
	nserror error = NSERROR_OK;

	switch (event->type) {
	case LLCACHE_EVENT_HAD_HEADERS:
		/* Will never happen: handled in hlcache */
		break;
	case LLCACHE_EVENT_HAD_DATA:
		if (c->handler->process_data != NULL) {
			if (c->handler->process_data(c, 
					(const char *) event->data.data.buf, 
					event->data.data.len) == false) {
				llcache_handle_abort(c->llcache);
				c->status = CONTENT_STATUS_ERROR;
				/** \todo It's not clear what error this is */
				error = NSERROR_NOMEM;
			}
		}
		break;
	case LLCACHE_EVENT_DONE:
	{
		size_t source_size;

		(void) llcache_handle_get_source_data(llcache, &source_size);

		content_set_status(c, messages_get("Processing"));
		msg_data.explicit_status_text = NULL;
		content_broadcast(c, CONTENT_MSG_STATUS, msg_data);

		content_convert(c);
	}
		break;
	case LLCACHE_EVENT_ERROR:
		/** \todo Error page? */
		c->status = CONTENT_STATUS_ERROR;
		msg_data.error = event->data.msg;
		content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
		break;
	case LLCACHE_EVENT_PROGRESS:
		content_set_status(c, event->data.msg);
		msg_data.explicit_status_text = NULL;
		content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
		break;
	case LLCACHE_EVENT_REDIRECT:
		msg_data.redirect.from = event->data.redirect.from;
		msg_data.redirect.to = event->data.redirect.to;
		content_broadcast(c, CONTENT_MSG_REDIRECT, msg_data);
		break;
	}

	return error;
}
Ejemplo n.º 5
0
/**
 * Abort a content object
 *
 * \param c The content object to abort
 * \return NSERROR_OK on success, otherwise appropriate error
 */
nserror content_abort(struct content *c)
{
	LOG("Aborting %p", c);
	
	if (c->handler->stop != NULL)
		c->handler->stop(c);
	
	/* And for now, abort our llcache object */
	return llcache_handle_abort(c->llcache);
}
Ejemplo n.º 6
0
/**
 * Migrate a retrieval context into its final destination content
 *
 * \param ctx             Context to migrate
 * \param effective_type  The effective MIME type of the content, or NULL
 * \return NSERROR_OK on success,
 *         NSERROR_NEED_DATA on success where data is needed,
 *         appropriate error otherwise
 */
static nserror hlcache_migrate_ctx(hlcache_retrieval_ctx *ctx,
		lwc_string *effective_type)
{
	content_type type = CONTENT_NONE;
	nserror error = NSERROR_OK;

	ctx->migrate_target = true;

	if (effective_type != NULL &&
			hlcache_type_is_acceptable(effective_type,
			ctx->accepted_types, &type)) {
		error = hlcache_find_content(ctx, effective_type);
		if (error != NSERROR_OK && error != NSERROR_NEED_DATA) {
			if (ctx->handle->cb != NULL) {
				hlcache_event hlevent;

				hlevent.type = CONTENT_MSG_ERROR;
				hlevent.data.error = messages_get("MiscError");

				ctx->handle->cb(ctx->handle, &hlevent,
						ctx->handle->pw);
			}

			llcache_handle_abort(ctx->llcache);
			llcache_handle_release(ctx->llcache);
		}
	} else if (type == CONTENT_NONE &&
			(ctx->flags & HLCACHE_RETRIEVE_MAY_DOWNLOAD)) {
		/* Unknown type, and we can download, so convert */
		llcache_handle_force_stream(ctx->llcache);

		if (ctx->handle->cb != NULL) {
			hlcache_event hlevent;

			hlevent.type = CONTENT_MSG_DOWNLOAD;
			hlevent.data.download = ctx->llcache;

			ctx->handle->cb(ctx->handle, &hlevent,
					ctx->handle->pw);
		}

		/* Ensure caller knows we need data */
		error = NSERROR_NEED_DATA;
	} else {
		/* Unacceptable type: report error */
		if (ctx->handle->cb != NULL) {
			hlcache_event hlevent;

			hlevent.type = CONTENT_MSG_ERROR;
			hlevent.data.error = messages_get("UnacceptableType");

			ctx->handle->cb(ctx->handle, &hlevent,
					ctx->handle->pw);
		}

		llcache_handle_abort(ctx->llcache);
		llcache_handle_release(ctx->llcache);
	}

	ctx->migrate_target = false;

	/* No longer require retrieval context */
	RING_REMOVE(hlcache->retrieval_ctx_ring, ctx);
	free((char *) ctx->child.charset);
	free(ctx);

	return error;
}
Ejemplo n.º 7
0
/* See download.h for documentation */
void download_context_abort(download_context *ctx)
{
	llcache_handle_abort(ctx->llcache);
}