Example #1
0
bool favicon_get_icon(struct content *c, xmlNode *html)
{
	static const content_type permitted_types[] = {
#ifdef WITH_BMP
		CONTENT_ICO,
#endif
#if defined(WITH_MNG) || defined(WITH_PNG)
		CONTENT_PNG,
#endif
#ifdef WITH_GIF
		CONTENT_GIF,
#endif
		CONTENT_UNKNOWN
	};
	char *url;
	nserror error;

	url = favicon_get_icon_ref(c, html);
	if (url == NULL)
		return false;

	error = hlcache_handle_retrieve(url, LLCACHE_RETRIEVE_NO_ERROR_PAGES, 
			content__get_url(c), NULL, favicon_callback, c, NULL, 
			permitted_types, &c->data.html.favicon);	

	if (error == NSERROR_OK) {
		c->active += 1;
	}
	
	free(url);

	return error == NSERROR_OK;
}
Example #2
0
/* exported interface documented in render/html_internal.h */
nserror html_css_quirks_stylesheets(html_content *c)
{
	nserror ns_error = NSERROR_OK;
	hlcache_child_context child;

	assert(c->stylesheets != NULL);

	if (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL) {
		child.charset = c->encoding;
		child.quirks = c->base.quirks;

		ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url,
				0, content_get_url(&c->base), NULL,
				html_convert_css_callback, c, &child,
				CONTENT_CSS,
				&c->stylesheets[STYLESHEET_QUIRKS].sheet);
		if (ns_error != NSERROR_OK) {
			return ns_error;
		}

		c->base.active++;
		LOG("%d fetches active", c->base.active);
	}

	return ns_error;
}
Example #3
0
static nserror
html_stylesheet_from_domnode(html_content *c,
			     dom_node *node,
			     hlcache_handle **sheet)
{
	hlcache_child_context child;
	dom_string *style;
	nsurl *url;
	dom_exception exc;
	nserror error;
	uint32_t key;
	char urlbuf[64];

	child.charset = c->encoding;
	child.quirks = c->base.quirks;

	exc = dom_node_get_text_content(node, &style);
	if ((exc != DOM_NO_ERR) || (style == NULL)) {
		LOG("No text content");
		return NSERROR_OK;
	}

	error = html_css_fetcher_add_item(style, c->base_url, &key);
	if (error != NSERROR_OK) {
		dom_string_unref(style);
		return error;
	}

	dom_string_unref(style);

	snprintf(urlbuf, sizeof(urlbuf), "x-ns-css:%u", key);

	error = nsurl_create(urlbuf, &url);
	if (error != NSERROR_OK) {
		return error;
	}

	error = hlcache_handle_retrieve(url, 0,
			content_get_url(&c->base), NULL,
			html_convert_css_callback, c, &child, CONTENT_CSS,
			sheet);
	if (error != NSERROR_OK) {
		nsurl_unref(url);
		return error;
	}

	nsurl_unref(url);

	c->base.active++;
	LOG("%d fetches active", c->base.active);

	return NSERROR_OK;
}
Example #4
0
/* exported interface documented in render/html_internal.h */
bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
		content_type permitted_types,
		int available_width, int available_height,
		bool background)
{
	struct content_html_object *object;
	hlcache_child_context child;
	nserror error;

	/* If we've already been aborted, don't bother attempting the fetch */
	if (c->aborted)
		return true;

	child.charset = c->encoding;
	child.quirks = c->base.quirks;

	object = calloc(1, sizeof(struct content_html_object));
	if (object == NULL) {
		return false;
	}

	object->parent = (struct content *) c;
	object->next = NULL;
	object->content = NULL;
	object->box = box;
	object->permitted_types = permitted_types;
	object->background = background;

	error = hlcache_handle_retrieve(url,
			HLCACHE_RETRIEVE_SNIFF_TYPE,
			content_get_url(&c->base), NULL,
			html_object_callback, object, &child,
			object->permitted_types, &object->content);
       	if (error != NSERROR_OK) {
		free(object);
		return error != NSERROR_NOMEM;
	}

	/* add to content object list */
	object->next = c->object_list;
	c->object_list = object;

	c->num_objects++;
	if (box != NULL) {
		c->base.active++;
		LOG("%d fetches active", c->base.active);
	}

	return true;
}
Example #5
0
static bool html_replace_object(struct content_html_object *object, nsurl *url)
{
	html_content *c;
	hlcache_child_context child;
	html_content *page;
	nserror error;

	assert(object != NULL);
	assert(object->box != NULL);

	c = (html_content *) object->parent;

	child.charset = c->encoding;
	child.quirks = c->base.quirks;

	if (object->content != NULL) {
		/* remove existing object */
		if (content_get_status(object->content) != CONTENT_STATUS_DONE) {
			c->base.active--;
			LOG("%d fetches active", c->base.active);
		}

		hlcache_handle_release(object->content);
		object->content = NULL;

		object->box->object = NULL;
	}

	/* initialise fetch */
	error = hlcache_handle_retrieve(url, HLCACHE_RETRIEVE_SNIFF_TYPE,
			content_get_url(&c->base), NULL,
			html_object_callback, object, &child,
			object->permitted_types,
			&object->content);

	if (error != NSERROR_OK)
		return false;

	for (page = c; page != NULL; page = page->page) {
		page->base.active++;
		LOG("%d fetches active", c->base.active);

		page->base.status = CONTENT_STATUS_READY;
	}

	return true;
}
Example #6
0
/**
 * Handle notification of the need for an imported stylesheet
 *
 * \param pw      CSS object requesting the import
 * \param parent  Stylesheet requesting the import
 * \param url     URL of the imported sheet
 * \param media   Applicable media for the imported sheet
 * \return CSS_OK on success, appropriate error otherwise
 */
css_error nscss_handle_import(void *pw, css_stylesheet *parent,
		lwc_string *url, uint64_t media)
{
	content_type accept = CONTENT_CSS;
	struct content_css_data *c = pw;
	nscss_import_ctx *ctx;
	hlcache_child_context child;
	struct nscss_import *imports;
	const char *referer;
	css_error error;
	nserror nerror;

	nsurl *ns_url;
	nsurl *ns_ref;

	assert(parent == c->sheet);

	error = css_stylesheet_get_url(c->sheet, &referer);
	if (error != CSS_OK) {
		return error;
	}

	ctx = malloc(sizeof(*ctx));
	if (ctx == NULL)
		return CSS_NOMEM;

	ctx->css = c;
	ctx->index = c->import_count;

	/* Increase space in table */
	imports = realloc(c->imports, (c->import_count + 1) * 
			sizeof(struct nscss_import));
	if (imports == NULL) {
		free(ctx);
		return CSS_NOMEM;
	}
	c->imports = imports;

	/** \todo fallback charset */
	child.charset = NULL;
	error = css_stylesheet_quirks_allowed(c->sheet, &child.quirks);
	if (error != CSS_OK) {
		free(ctx);
		return error;
	}

	/* Create content */
	c->imports[c->import_count].media = media;

	/* TODO: Why aren't we getting a relative url part, to join? */
	nerror = nsurl_create(lwc_string_data(url), &ns_url);
	if (nerror != NSERROR_OK) {
		free(ctx);
		return CSS_NOMEM;
	}

	/* TODO: Constructing nsurl for referer here is silly, avoid */
	nerror = nsurl_create(referer, &ns_ref);
	if (nerror != NSERROR_OK) {
		nsurl_unref(ns_url);
		free(ctx);
		return CSS_NOMEM;
	}

	/* Avoid importing ourself */
	if (nsurl_compare(ns_url, ns_ref, NSURL_COMPLETE)) {
		c->imports[c->import_count].c = NULL;
		/* No longer require context as we're not fetching anything */
		free(ctx);
		ctx = NULL;
	} else {
		nerror = hlcache_handle_retrieve(ns_url,
				0, ns_ref, NULL, nscss_import, ctx,
				&child, accept,
				&c->imports[c->import_count].c);
		if (nerror != NSERROR_OK) {
			free(ctx);
			return CSS_NOMEM;
		}
	}

	nsurl_unref(ns_url);
	nsurl_unref(ns_ref);

#ifdef NSCSS_IMPORT_TRACE
	LOG(("Import %d '%s' -> (handle: %p ctx: %p)", 
			c->import_count, lwc_string_data(url), 
			c->imports[c->import_count].c, ctx));
#endif

	c->import_count++;

	return CSS_OK;
}
Example #7
0
/* exported interface documented in render/html_internal.h */
nserror html_css_new_stylesheets(html_content *c)
{
	nserror ns_error;
	hlcache_child_context child;

	if (c->stylesheets != NULL) {
		return NSERROR_OK; /* already initialised */
	}

	/* stylesheet 0 is the base style sheet,
	 * stylesheet 1 is the quirks mode style sheet,
	 * stylesheet 2 is the adblocking stylesheet,
	 * stylesheet 3 is the user stylesheet */
	c->stylesheets = calloc(STYLESHEET_START,
			sizeof(struct html_stylesheet));
	if (c->stylesheets == NULL) {
		return NSERROR_NOMEM;
	}

	c->stylesheets[STYLESHEET_BASE].sheet = NULL;
	c->stylesheets[STYLESHEET_QUIRKS].sheet = NULL;
	c->stylesheets[STYLESHEET_ADBLOCK].sheet = NULL;
	c->stylesheets[STYLESHEET_USER].sheet = NULL;
	c->stylesheet_count = STYLESHEET_START;

	child.charset = c->encoding;
	child.quirks = c->base.quirks;

	ns_error = hlcache_handle_retrieve(html_default_stylesheet_url, 0,
			content_get_url(&c->base), NULL,
			html_convert_css_callback, c, &child, CONTENT_CSS,
			&c->stylesheets[STYLESHEET_BASE].sheet);
	if (ns_error != NSERROR_OK) {
		return ns_error;
	}

	c->base.active++;
	LOG("%d fetches active", c->base.active);


	if (nsoption_bool(block_advertisements)) {
		ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url,
				0, content_get_url(&c->base), NULL,
				html_convert_css_callback,
				c, &child, CONTENT_CSS,
				&c->stylesheets[STYLESHEET_ADBLOCK].sheet);
		if (ns_error != NSERROR_OK) {
			return ns_error;
		}

		c->base.active++;
		LOG("%d fetches active", c->base.active);

	}

	ns_error = hlcache_handle_retrieve(html_user_stylesheet_url, 0,
			content_get_url(&c->base), NULL,
			html_convert_css_callback, c, &child, CONTENT_CSS,
			&c->stylesheets[STYLESHEET_USER].sheet);
	if (ns_error != NSERROR_OK) {
		return ns_error;
	}

	c->base.active++;
	LOG("%d fetches active", c->base.active);

	return ns_error;
}
Example #8
0
bool html_css_process_link(html_content *htmlc, dom_node *node)
{
	dom_string *rel, *type_attr, *media, *href;
	struct html_stylesheet *stylesheets;
	nsurl *joined;
	dom_exception exc;
	nserror ns_error;
	hlcache_child_context child;

	/* rel=<space separated list, including 'stylesheet'> */
	exc = dom_element_get_attribute(node, corestring_dom_rel, &rel);
	if (exc != DOM_NO_ERR || rel == NULL)
		return true;

	if (strcasestr(dom_string_data(rel), "stylesheet") == 0) {
		dom_string_unref(rel);
		return true;
	} else if (strcasestr(dom_string_data(rel), "alternate") != 0) {
		/* Ignore alternate stylesheets */
		dom_string_unref(rel);
		return true;
	}
	dom_string_unref(rel);

	/* type='text/css' or not present */
	exc = dom_element_get_attribute(node, corestring_dom_type, &type_attr);
	if (exc == DOM_NO_ERR && type_attr != NULL) {
		if (!dom_string_caseless_lwc_isequal(type_attr,
				corestring_lwc_text_css)) {
			dom_string_unref(type_attr);
			return true;
		}
		dom_string_unref(type_attr);
	}

	/* media contains 'screen' or 'all' or not present */
	exc = dom_element_get_attribute(node, corestring_dom_media, &media);
	if (exc == DOM_NO_ERR && media != NULL) {
		if (strcasestr(dom_string_data(media), "screen") == NULL &&
		    strcasestr(dom_string_data(media), "all") == NULL) {
			dom_string_unref(media);
			return true;
		}
		dom_string_unref(media);
	}

	/* href='...' */
	exc = dom_element_get_attribute(node, corestring_dom_href, &href);
	if (exc != DOM_NO_ERR || href == NULL)
		return true;

	/* TODO: only the first preferred stylesheets (ie.
	 * those with a title attribute) should be loaded
	 * (see HTML4 14.3) */

	ns_error = nsurl_join(htmlc->base_url, dom_string_data(href), &joined);
	if (ns_error != NSERROR_OK) {
		dom_string_unref(href);
		goto no_memory;
	}
	dom_string_unref(href);

	LOG("linked stylesheet %i '%s'", htmlc->stylesheet_count, nsurl_access(joined));

	/* extend stylesheets array to allow for new sheet */
	stylesheets = realloc(htmlc->stylesheets,
			      sizeof(struct html_stylesheet) *
			      (htmlc->stylesheet_count + 1));
	if (stylesheets == NULL) {
		nsurl_unref(joined);
		ns_error = NSERROR_NOMEM;
		goto no_memory;
	}

	htmlc->stylesheets = stylesheets;
	htmlc->stylesheets[htmlc->stylesheet_count].node = NULL;
	htmlc->stylesheets[htmlc->stylesheet_count].modified = false;

	/* start fetch */
	child.charset = htmlc->encoding;
	child.quirks = htmlc->base.quirks;

	ns_error = hlcache_handle_retrieve(joined, 0,
			content_get_url(&htmlc->base),
			NULL, html_convert_css_callback,
			htmlc, &child, CONTENT_CSS,
			&htmlc->stylesheets[htmlc->stylesheet_count].sheet);

	nsurl_unref(joined);

	if (ns_error != NSERROR_OK)
		goto no_memory;

	htmlc->stylesheet_count++;

	htmlc->base.active++;
	LOG("%d fetches active", htmlc->base.active);

	return true;

no_memory:
	content_broadcast_errorcode(&htmlc->base, ns_error);
	return false;
}
Example #9
0
/**
 * process a script with a src tag
 */
static dom_hubbub_error
exec_src_script(html_content *c,
		dom_node *node,
		dom_string *mimetype,
		dom_string *src)
{
	nserror ns_error;
	nsurl *joined;
	hlcache_child_context child;
	struct html_script *nscript;
	union content_msg_data msg_data;
	bool async;
	bool defer;
	enum html_script_type script_type;
	hlcache_handle_callback script_cb;
	dom_hubbub_error ret = DOM_HUBBUB_OK;
	dom_exception exc; /* returned by libdom functions */

	/* src url */
	ns_error = nsurl_join(c->base_url, dom_string_data(src), &joined);
	if (ns_error != NSERROR_OK) {
		msg_data.error = messages_get("NoMemory");
		content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
		return DOM_HUBBUB_NOMEM;
	}

	LOG(("script %i '%s'", c->scripts_count, nsurl_access(joined)));

	/* there are three ways to process the script tag at this point:
	 *
	 * Syncronously  pause the parent parse and continue after
	 *                 the script has downloaded and executed. (default)
	 * Async         Start the script downloading and execute it when it 
	 *                 becomes available. 
	 * Defered       Start the script downloading and execute it when 
	 *                 the page has completed parsing, may be set along 
	 *                 with async where it is ignored.
	 */

	/* we interpret the presence of the async and defer attribute
	 * as true and ignore its value, technically only the empty
	 * value or the attribute name itself are valid. However
	 * various browsers interpret this in various ways the most
	 * compatible approach is to be liberal and accept any
	 * value. Note setting the values to "false" still makes them true! 
	 */
	exc = dom_element_has_attribute(node, corestring_dom_async, &async);
	if (exc != DOM_NO_ERR) {
		return DOM_HUBBUB_OK; /* dom error */
	}

	if (async) {
		/* asyncronous script */
		script_type = HTML_SCRIPT_ASYNC;
		script_cb = convert_script_async_cb;

	} else {
		exc = dom_element_has_attribute(node, 
						corestring_dom_defer, &defer);
		if (exc != DOM_NO_ERR) {
			return DOM_HUBBUB_OK; /* dom error */
		}

		if (defer) {
			/* defered script */
			script_type = HTML_SCRIPT_DEFER;
			script_cb = convert_script_defer_cb;
		} else {
			/* syncronous script */
			script_type = HTML_SCRIPT_SYNC;
			script_cb = convert_script_sync_cb;
		}
	}

	nscript = html_process_new_script(c, mimetype, script_type);
	if (nscript == NULL) {
		nsurl_unref(joined);
		msg_data.error = messages_get("NoMemory");
		content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
		return DOM_HUBBUB_NOMEM;
	}

	/* set up child fetch encoding and quirks */
	child.charset = c->encoding;
	child.quirks = c->base.quirks;

	ns_error = hlcache_handle_retrieve(joined,
					   0,
					   content_get_url(&c->base),
					   NULL,
					   script_cb,
					   c,
					   &child,
					   CONTENT_SCRIPT,
					   &nscript->data.handle);


	nsurl_unref(joined);

	if (ns_error != NSERROR_OK) {
		/* @todo Deal with fetch error better. currently assume
		 * fetch never became active 
		 */
		/* mark duff script fetch as already started */
		nscript->already_started = true; 
		LOG(("Fetch failed with error %d",ns_error));
	} else {
		/* update base content active fetch count */
		c->base.active++; 
		LOG(("%d fetches active", c->base.active));

		switch (script_type) {
		case HTML_SCRIPT_SYNC:
			ret =  DOM_HUBBUB_HUBBUB_ERR | HUBBUB_PAUSED;

		case HTML_SCRIPT_ASYNC:
			break;

		case HTML_SCRIPT_DEFER:
			break;

		default:
			assert(0);
		}
	}

	return ret;
}