mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-22 12:12:35 +03:00
metadata links stored in contents
browser uses metadata links for favicons svn path=/trunk/netsurf/; revision=12977
This commit is contained in:
parent
52ad2c1e25
commit
230779848e
@ -376,6 +376,8 @@ void content__reformat(struct content *c, bool background,
|
|||||||
|
|
||||||
void content_destroy(struct content *c)
|
void content_destroy(struct content *c)
|
||||||
{
|
{
|
||||||
|
struct content_rfc5988_link *link;
|
||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
LOG(("content %p %s", c,
|
LOG(("content %p %s", c,
|
||||||
nsurl_access(llcache_handle_get_url(c->llcache))));
|
nsurl_access(llcache_handle_get_url(c->llcache))));
|
||||||
@ -389,6 +391,12 @@ void content_destroy(struct content *c)
|
|||||||
|
|
||||||
lwc_string_unref(c->mime_type);
|
lwc_string_unref(c->mime_type);
|
||||||
|
|
||||||
|
/* release metadata links */
|
||||||
|
link = c->links;
|
||||||
|
while (link != NULL) {
|
||||||
|
link = content__free_rfc5988_link(link);
|
||||||
|
}
|
||||||
|
|
||||||
talloc_free(c);
|
talloc_free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,6 +752,97 @@ bool content__set_title(struct content *c, const char *title)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct content_rfc5988_link *
|
||||||
|
content_find_rfc5988_link(hlcache_handle *h, lwc_string *rel)
|
||||||
|
{
|
||||||
|
struct content *c = hlcache_handle_get_content(h);
|
||||||
|
struct content_rfc5988_link *link = c->links;
|
||||||
|
bool rel_match = false;
|
||||||
|
|
||||||
|
while (link != NULL) {
|
||||||
|
lwc_string_caseless_isequal(link->rel, rel, &rel_match);
|
||||||
|
if (rel_match) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
link = link->next;
|
||||||
|
}
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct content_rfc5988_link *
|
||||||
|
content__free_rfc5988_link(struct content_rfc5988_link *link)
|
||||||
|
{
|
||||||
|
struct content_rfc5988_link *next;
|
||||||
|
|
||||||
|
next = link->next;
|
||||||
|
|
||||||
|
lwc_string_unref(link->rel);
|
||||||
|
nsurl_unref(link->href);
|
||||||
|
if (link->hreflang != NULL) {
|
||||||
|
lwc_string_unref(link->hreflang);
|
||||||
|
}
|
||||||
|
if (link->type != NULL) {
|
||||||
|
lwc_string_unref(link->type);
|
||||||
|
}
|
||||||
|
if (link->media != NULL) {
|
||||||
|
lwc_string_unref(link->media);
|
||||||
|
}
|
||||||
|
if (link->sizes != NULL) {
|
||||||
|
lwc_string_unref(link->sizes);
|
||||||
|
}
|
||||||
|
free(link);
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool content__add_rfc5988_link(struct content *c,
|
||||||
|
const struct content_rfc5988_link *link)
|
||||||
|
{
|
||||||
|
struct content_rfc5988_link *newlink;
|
||||||
|
union content_msg_data msg_data;
|
||||||
|
|
||||||
|
/* a link relation must be present for it to be a link */
|
||||||
|
if (link->rel == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* a link href must be present for it to be a link */
|
||||||
|
if (link->href == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
newlink = calloc(1, sizeof(struct content_rfc5988_link));
|
||||||
|
if (newlink == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy values */
|
||||||
|
newlink->rel = lwc_string_ref(link->rel);
|
||||||
|
newlink->href = nsurl_ref(link->href);
|
||||||
|
if (link->hreflang != NULL) {
|
||||||
|
newlink->hreflang = lwc_string_ref(link->hreflang);
|
||||||
|
}
|
||||||
|
if (link->type != NULL) {
|
||||||
|
newlink->type = lwc_string_ref(link->type);
|
||||||
|
}
|
||||||
|
if (link->media != NULL) {
|
||||||
|
newlink->media = lwc_string_ref(link->media);
|
||||||
|
}
|
||||||
|
if (link->sizes != NULL) {
|
||||||
|
newlink->sizes = lwc_string_ref(link->sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add to metadata link to list */
|
||||||
|
newlink->next = c->links;
|
||||||
|
c->links = newlink;
|
||||||
|
|
||||||
|
/* broadcast the data */
|
||||||
|
msg_data.rfc5988_link = newlink;
|
||||||
|
content_broadcast(c, CONTENT_MSG_LINK, msg_data);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve computed type of content
|
* Retrieve computed type of content
|
||||||
*
|
*
|
||||||
|
@ -75,6 +75,18 @@ typedef enum {
|
|||||||
CONTENT_MSG_LINK, /**< RFC5988 link */
|
CONTENT_MSG_LINK, /**< RFC5988 link */
|
||||||
} content_msg;
|
} content_msg;
|
||||||
|
|
||||||
|
/** RFC5988 metadata link */
|
||||||
|
struct content_rfc5988_link {
|
||||||
|
struct content_rfc5988_link *next; /**< next rfc5988_link in list */
|
||||||
|
|
||||||
|
lwc_string *rel; /**< the link relationship - must be present */
|
||||||
|
nsurl *href; /* the link href - must be present */
|
||||||
|
lwc_string *hreflang;
|
||||||
|
lwc_string *type;
|
||||||
|
lwc_string *media;
|
||||||
|
lwc_string *sizes;
|
||||||
|
};
|
||||||
|
|
||||||
/** Extra data for some content_msg messages. */
|
/** Extra data for some content_msg messages. */
|
||||||
union content_msg_data {
|
union content_msg_data {
|
||||||
const char *error; /**< Error message, for CONTENT_MSG_ERROR. */
|
const char *error; /**< Error message, for CONTENT_MSG_ERROR. */
|
||||||
@ -97,11 +109,7 @@ union content_msg_data {
|
|||||||
/** Low-level cache handle, for CONTENT_MSG_DOWNLOAD */
|
/** Low-level cache handle, for CONTENT_MSG_DOWNLOAD */
|
||||||
struct llcache_handle *download;
|
struct llcache_handle *download;
|
||||||
/** rfc5988 link data CONTENT_MSG_RFC5988_LINK */
|
/** rfc5988 link data CONTENT_MSG_RFC5988_LINK */
|
||||||
struct {
|
struct content_rfc5988_link *rfc5988_link;
|
||||||
nsurl *url;
|
|
||||||
char *rel;
|
|
||||||
char *type;
|
|
||||||
} rfc5988_link;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -167,6 +175,8 @@ void content_close(struct hlcache_handle *h);
|
|||||||
struct selection *content_get_selection(struct hlcache_handle *h);
|
struct selection *content_get_selection(struct hlcache_handle *h);
|
||||||
void content_get_contextual_content(struct hlcache_handle *h,
|
void content_get_contextual_content(struct hlcache_handle *h,
|
||||||
int x, int y, struct contextual_content *data);
|
int x, int y, struct contextual_content *data);
|
||||||
|
struct content_rfc5988_link *content_find_rfc5988_link(struct hlcache_handle *c,
|
||||||
|
lwc_string *rel);
|
||||||
|
|
||||||
/* Member accessors */
|
/* Member accessors */
|
||||||
content_type content_get_type(struct hlcache_handle *c);
|
content_type content_get_type(struct hlcache_handle *c);
|
||||||
|
@ -108,6 +108,8 @@ struct content {
|
|||||||
|
|
||||||
nsurl *refresh; /**< URL for refresh request */
|
nsurl *refresh; /**< URL for refresh request */
|
||||||
|
|
||||||
|
struct content_rfc5988_link *links; /**< list of metadata links */
|
||||||
|
|
||||||
unsigned int time; /**< Creation time,
|
unsigned int time; /**< Creation time,
|
||||||
if LOADING or READY,
|
if LOADING or READY,
|
||||||
otherwise total time. */
|
otherwise total time. */
|
||||||
@ -160,6 +162,11 @@ void content_broadcast(struct content *c, content_msg msg,
|
|||||||
void content_add_error(struct content *c, const char *token,
|
void content_add_error(struct content *c, const char *token,
|
||||||
unsigned int line);
|
unsigned int line);
|
||||||
|
|
||||||
|
bool content__add_rfc5988_link(struct content *c,
|
||||||
|
const struct content_rfc5988_link *link);
|
||||||
|
struct content_rfc5988_link *content__free_rfc5988_link(
|
||||||
|
struct content_rfc5988_link *link);
|
||||||
|
|
||||||
void content__reformat(struct content *c, bool background,
|
void content__reformat(struct content *c, bool background,
|
||||||
int width, int height);
|
int width, int height);
|
||||||
void content__request_redraw(struct content *c,
|
void content__request_redraw(struct content *c,
|
||||||
|
@ -877,6 +877,8 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
|
|||||||
nsurl_unref(nsref);
|
nsurl_unref(nsref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for fetchcache() for browser window favicon fetches.
|
* Callback for fetchcache() for browser window favicon fetches.
|
||||||
*/
|
*/
|
||||||
@ -889,16 +891,47 @@ static nserror browser_window_favicon_callback(hlcache_handle *c,
|
|||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case CONTENT_MSG_DONE:
|
case CONTENT_MSG_DONE:
|
||||||
LOG(("favicon contents for %p done!", bw));
|
LOG(("favicon contents for %p done!", bw));
|
||||||
/* content_get_bitmap on the bw->favicon should give
|
|
||||||
us the favicon at this point
|
if (bw->current_favicon != NULL) {
|
||||||
*/
|
content_status status =
|
||||||
|
content_get_status(bw->current_favicon);
|
||||||
|
|
||||||
|
if ((status == CONTENT_STATUS_READY) ||
|
||||||
|
(status == CONTENT_STATUS_DONE))
|
||||||
|
content_close(bw->current_favicon);
|
||||||
|
|
||||||
|
hlcache_handle_release(bw->current_favicon);
|
||||||
|
}
|
||||||
|
|
||||||
|
bw->current_favicon = c;
|
||||||
|
bw->loading_favicon = NULL;
|
||||||
|
|
||||||
|
/* content_get_bitmap on the hlcache_handle should give
|
||||||
|
* us the favicon bitmap at this point
|
||||||
|
*/
|
||||||
if (bw->window != NULL) {
|
if (bw->window != NULL) {
|
||||||
gui_window_set_icon(bw->window, bw->favicon);
|
gui_window_set_icon(bw->window, c);
|
||||||
} else {
|
} else {
|
||||||
LOG(("null browser window on favicon!"));
|
LOG(("null browser window on favicon!"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CONTENT_MSG_ERROR:
|
||||||
|
|
||||||
|
/* clean up after ourselves */
|
||||||
|
if (c == bw->loading_favicon)
|
||||||
|
bw->loading_favicon = NULL;
|
||||||
|
else if (c == bw->current_favicon) {
|
||||||
|
bw->current_favicon = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlcache_handle_release(c);
|
||||||
|
|
||||||
|
/** @todo if this was not the default
|
||||||
|
* resource:favicon.png start a fetch for it.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG(("favicon unhandled event"));
|
LOG(("favicon unhandled event"));
|
||||||
break;
|
break;
|
||||||
@ -906,6 +939,57 @@ static nserror browser_window_favicon_callback(hlcache_handle *c,
|
|||||||
return NSERROR_OK;
|
return NSERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void browser_window_update_favicon(hlcache_handle *c,
|
||||||
|
struct browser_window *bw)
|
||||||
|
{
|
||||||
|
lwc_string *icon_str;
|
||||||
|
struct content_rfc5988_link *link;
|
||||||
|
nsurl *nsref = NULL;
|
||||||
|
nsurl *nsurl;
|
||||||
|
nserror error;
|
||||||
|
|
||||||
|
/* already fetching the favicon - use that */
|
||||||
|
if (bw->loading_favicon != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* look for favicon metadata link */
|
||||||
|
lwc_intern_string("icon", SLEN("icon"), &icon_str);
|
||||||
|
link = content_find_rfc5988_link(c, icon_str);
|
||||||
|
lwc_string_unref(icon_str);
|
||||||
|
|
||||||
|
if (link == NULL) {
|
||||||
|
lwc_intern_string("shortcut icon", SLEN("shortcut_icon"),
|
||||||
|
&icon_str);
|
||||||
|
link = content_find_rfc5988_link(c, icon_str);
|
||||||
|
lwc_string_unref(icon_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link == NULL) {
|
||||||
|
/* no favicon via link, try for the default location - bletch */
|
||||||
|
error = nsurl_join(content_get_url(c), "/favicon.ico", &nsurl);
|
||||||
|
if (error != NSERROR_OK) {
|
||||||
|
LOG(("Unable to create default location url"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nsurl = link->href;
|
||||||
|
nsurl_ref(nsurl);
|
||||||
|
}
|
||||||
|
|
||||||
|
hlcache_handle_retrieve(nsurl,
|
||||||
|
HLCACHE_RETRIEVE_MAY_DOWNLOAD |
|
||||||
|
HLCACHE_RETRIEVE_SNIFF_TYPE,
|
||||||
|
nsref,
|
||||||
|
NULL,
|
||||||
|
browser_window_favicon_callback,
|
||||||
|
bw,
|
||||||
|
NULL,
|
||||||
|
CONTENT_IMAGE,
|
||||||
|
&bw->loading_favicon);
|
||||||
|
|
||||||
|
nsurl_unref(nsurl);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for fetchcache() for browser window fetches.
|
* Callback for fetchcache() for browser window fetches.
|
||||||
*/
|
*/
|
||||||
@ -962,18 +1046,6 @@ nserror browser_window_callback(hlcache_handle *c,
|
|||||||
hlcache_handle_release(bw->current_content);
|
hlcache_handle_release(bw->current_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bw->favicon != NULL) {
|
|
||||||
content_status status =
|
|
||||||
content_get_status(bw->favicon);
|
|
||||||
|
|
||||||
if (status == CONTENT_STATUS_READY ||
|
|
||||||
status == CONTENT_STATUS_DONE)
|
|
||||||
content_close(bw->favicon);
|
|
||||||
|
|
||||||
hlcache_handle_release(bw->favicon);
|
|
||||||
bw->favicon = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bw->current_content = c;
|
bw->current_content = c;
|
||||||
bw->loading_content = NULL;
|
bw->loading_content = NULL;
|
||||||
|
|
||||||
@ -1040,32 +1112,7 @@ nserror browser_window_callback(hlcache_handle *c,
|
|||||||
browser_window_update(bw, false);
|
browser_window_update(bw, false);
|
||||||
browser_window_set_status(bw, content_get_status_message(c));
|
browser_window_set_status(bw, content_get_status_message(c));
|
||||||
browser_window_stop_throbber(bw);
|
browser_window_stop_throbber(bw);
|
||||||
if (bw->favicon == NULL) {
|
browser_window_update_favicon(c, bw);
|
||||||
/* no favicon via link - try for the default location - bletch */
|
|
||||||
nsurl *nsref = NULL;
|
|
||||||
nsurl *nsurl;
|
|
||||||
nserror error;
|
|
||||||
|
|
||||||
error = nsurl_join(content_get_url(c), "/favicon.ico", &nsurl);
|
|
||||||
if (error == NSERROR_OK) {
|
|
||||||
|
|
||||||
|
|
||||||
hlcache_handle_retrieve(nsurl,
|
|
||||||
HLCACHE_RETRIEVE_MAY_DOWNLOAD |
|
|
||||||
HLCACHE_RETRIEVE_SNIFF_TYPE,
|
|
||||||
nsref,
|
|
||||||
NULL,
|
|
||||||
browser_window_favicon_callback,
|
|
||||||
bw,
|
|
||||||
NULL,
|
|
||||||
CONTENT_IMAGE,
|
|
||||||
&bw->favicon);
|
|
||||||
|
|
||||||
nsurl_unref(nsurl);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
history_update(bw->history, c);
|
history_update(bw->history, c);
|
||||||
hotlist_visited(c);
|
hotlist_visited(c);
|
||||||
@ -1145,13 +1192,26 @@ nserror browser_window_callback(hlcache_handle *c,
|
|||||||
case CONTENT_MSG_LINK: /* content has an rfc5988 link element */
|
case CONTENT_MSG_LINK: /* content has an rfc5988 link element */
|
||||||
{
|
{
|
||||||
nsurl *nsref = NULL;
|
nsurl *nsref = NULL;
|
||||||
if ((bw->favicon == NULL) &&
|
lwc_string *icon_str;
|
||||||
(strstr(event->data.rfc5988_link.rel, "icon") != NULL)) {
|
lwc_string *shortcut_icon_str;
|
||||||
/* its a favicon start a fetch for it */
|
bool icon_match;
|
||||||
LOG(("fetching favicon rel:%s '%s'",
|
bool shortcut_icon_match;
|
||||||
event->data.rfc5988_link.rel,
|
|
||||||
nsurl_access(event->data.rfc5988_link.url)));
|
lwc_intern_string("icon", SLEN("icon"), &icon_str);
|
||||||
hlcache_handle_retrieve(event->data.rfc5988_link.url,
|
lwc_intern_string("shortcut icon", SLEN("shortcut_icon"), &shortcut_icon_str);
|
||||||
|
lwc_string_caseless_isequal(event->data.rfc5988_link->rel, icon_str, &icon_match);
|
||||||
|
lwc_string_caseless_isequal(event->data.rfc5988_link->rel, shortcut_icon_str, &shortcut_icon_match);
|
||||||
|
lwc_string_unref(icon_str);
|
||||||
|
lwc_string_unref(shortcut_icon_str);
|
||||||
|
|
||||||
|
if ((bw->loading_favicon == NULL) &&
|
||||||
|
(icon_match || shortcut_icon_match)) {
|
||||||
|
/* its a favicon and we are not already fetching one
|
||||||
|
start a fetch for it */
|
||||||
|
LOG(("fetching favicon rel:%p '%s'",
|
||||||
|
event->data.rfc5988_link->rel,
|
||||||
|
nsurl_access(event->data.rfc5988_link->href)));
|
||||||
|
hlcache_handle_retrieve(event->data.rfc5988_link->href,
|
||||||
HLCACHE_RETRIEVE_MAY_DOWNLOAD |
|
HLCACHE_RETRIEVE_MAY_DOWNLOAD |
|
||||||
HLCACHE_RETRIEVE_SNIFF_TYPE,
|
HLCACHE_RETRIEVE_SNIFF_TYPE,
|
||||||
nsref,
|
nsref,
|
||||||
@ -1160,7 +1220,7 @@ nserror browser_window_callback(hlcache_handle *c,
|
|||||||
bw,
|
bw,
|
||||||
NULL,
|
NULL,
|
||||||
CONTENT_IMAGE,
|
CONTENT_IMAGE,
|
||||||
&bw->favicon);
|
&bw->loading_favicon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1724,16 +1784,21 @@ void browser_window_destroy_internal(struct browser_window *bw)
|
|||||||
bw->current_content = NULL;
|
bw->current_content = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bw->favicon != NULL) {
|
if (bw->loading_favicon != NULL) {
|
||||||
content_status status =
|
hlcache_handle_abort(bw->loading_favicon);
|
||||||
content_get_status(bw->favicon);
|
hlcache_handle_release(bw->loading_favicon);
|
||||||
|
bw->loading_favicon = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bw->current_favicon != NULL) {
|
||||||
|
content_status status = content_get_status(bw->current_favicon);
|
||||||
|
|
||||||
if (status == CONTENT_STATUS_READY ||
|
if (status == CONTENT_STATUS_READY ||
|
||||||
status == CONTENT_STATUS_DONE)
|
status == CONTENT_STATUS_DONE)
|
||||||
content_close(bw->favicon);
|
content_close(bw->current_favicon);
|
||||||
|
|
||||||
hlcache_handle_release(bw->favicon);
|
hlcache_handle_release(bw->current_favicon);
|
||||||
bw->favicon = NULL;
|
bw->current_favicon = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bw->box != NULL) {
|
if (bw->box != NULL) {
|
||||||
|
@ -76,7 +76,9 @@ struct browser_window {
|
|||||||
struct hlcache_handle *loading_content;
|
struct hlcache_handle *loading_content;
|
||||||
|
|
||||||
/** Page Favicon */
|
/** Page Favicon */
|
||||||
struct hlcache_handle *favicon;
|
struct hlcache_handle *current_favicon;
|
||||||
|
/** handle for favicon which we started loading early */
|
||||||
|
struct hlcache_handle *loading_favicon;
|
||||||
|
|
||||||
/** Window history structure. */
|
/** Window history structure. */
|
||||||
struct history *history;
|
struct history *history;
|
||||||
|
@ -283,7 +283,7 @@ static void image_cache__background_update(void *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* exported interface documented in image_cache.h */
|
/* exported interface documented in image_cache.h */
|
||||||
struct bitmap *image_cache_get_bitmap(struct content *c)
|
struct bitmap *image_cache_get_bitmap(const struct content *c)
|
||||||
{
|
{
|
||||||
struct image_cache_entry_s *centry;
|
struct image_cache_entry_s *centry;
|
||||||
|
|
||||||
@ -576,14 +576,7 @@ void image_cache_destroy(struct content *content)
|
|||||||
|
|
||||||
void *image_cache_get_internal(const struct content *c, void *context)
|
void *image_cache_get_internal(const struct content *c, void *context)
|
||||||
{
|
{
|
||||||
struct image_cache_entry_s *centry;
|
return image_cache_get_bitmap(c);
|
||||||
|
|
||||||
centry = image_cache__find(c);
|
|
||||||
if (centry == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return centry->bitmap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content_type image_cache_content_type(void)
|
content_type image_cache_content_type(void)
|
||||||
|
@ -79,7 +79,7 @@ nserror image_cache_remove(struct content *content);
|
|||||||
|
|
||||||
|
|
||||||
/** Obtain a bitmap from a content converting from source if neccessary. */
|
/** Obtain a bitmap from a content converting from source if neccessary. */
|
||||||
struct bitmap *image_cache_get_bitmap(struct content *c);
|
struct bitmap *image_cache_get_bitmap(const struct content *c);
|
||||||
|
|
||||||
/** Obtain a bitmap from a content with no conversion */
|
/** Obtain a bitmap from a content with no conversion */
|
||||||
struct bitmap *image_cache_find_bitmap(struct content *c);
|
struct bitmap *image_cache_find_bitmap(struct content *c);
|
||||||
|
101
render/html.c
101
render/html.c
@ -740,6 +740,78 @@ void html_box_convert_done(html_content *c, bool success)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** process link node */
|
||||||
|
static bool html_process_link(html_content *c, xmlNode *node)
|
||||||
|
{
|
||||||
|
struct content_rfc5988_link *link;
|
||||||
|
char *xmlstr;
|
||||||
|
nserror error;
|
||||||
|
lwc_string *rel;
|
||||||
|
nsurl *href;
|
||||||
|
|
||||||
|
/* check that the relation exists - w3c spec says must be present */
|
||||||
|
xmlstr = (char *)xmlGetProp(node, (const xmlChar *)"rel");
|
||||||
|
if (xmlstr == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lwc_intern_string(xmlstr, strlen(xmlstr), &rel);
|
||||||
|
xmlFree(xmlstr);
|
||||||
|
|
||||||
|
/* check that the href exists - w3c spec says must be present */
|
||||||
|
xmlstr = (char *)xmlGetProp(node, (const xmlChar *) "href");
|
||||||
|
if (xmlstr == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
error = nsurl_join(c->base_url, xmlstr, &href);
|
||||||
|
xmlFree(xmlstr);
|
||||||
|
if (error != NSERROR_OK) {
|
||||||
|
lwc_string_unref(rel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
link = calloc(1, sizeof(struct content_rfc5988_link));
|
||||||
|
if (link == NULL) {
|
||||||
|
lwc_string_unref(rel);
|
||||||
|
nsurl_unref(href);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
link->rel = rel;
|
||||||
|
link->href = href;
|
||||||
|
|
||||||
|
/* look for optional properties */
|
||||||
|
xmlstr = (char *)xmlGetProp(node, (const xmlChar *) "hreflang");
|
||||||
|
if (xmlstr != NULL) {
|
||||||
|
lwc_intern_string(xmlstr, strlen(xmlstr), &link->hreflang);
|
||||||
|
xmlFree(xmlstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlstr = (char *) xmlGetProp(node, (const xmlChar *) "type");
|
||||||
|
if (xmlstr != NULL) {
|
||||||
|
lwc_intern_string(xmlstr, strlen(xmlstr), &link->type);
|
||||||
|
xmlFree(xmlstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlstr = (char *) xmlGetProp(node, (const xmlChar *) "media");
|
||||||
|
if (xmlstr != NULL) {
|
||||||
|
lwc_intern_string(xmlstr, strlen(xmlstr), &link->media);
|
||||||
|
xmlFree(xmlstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlstr = (char *) xmlGetProp(node, (const xmlChar *) "sizes");
|
||||||
|
if (xmlstr != NULL) {
|
||||||
|
lwc_intern_string(xmlstr, strlen(xmlstr), &link->sizes);
|
||||||
|
xmlFree(xmlstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add to content */
|
||||||
|
content__add_rfc5988_link(&c->base, link);
|
||||||
|
|
||||||
|
/* release this copy */
|
||||||
|
content__free_rfc5988_link(link);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process elements in <head>.
|
* Process elements in <head>.
|
||||||
*
|
*
|
||||||
@ -811,34 +883,7 @@ bool html_head(html_content *c, xmlNode *head)
|
|||||||
xmlFree(s);
|
xmlFree(s);
|
||||||
}
|
}
|
||||||
} else if (strcmp((const char *) node->name, "link") == 0) {
|
} else if (strcmp((const char *) node->name, "link") == 0) {
|
||||||
union content_msg_data msg_data;
|
html_process_link(c, node);
|
||||||
char *href;
|
|
||||||
nserror error;
|
|
||||||
|
|
||||||
href = (char *) xmlGetProp(node, (const xmlChar *) "href");
|
|
||||||
if (href) {
|
|
||||||
error = nsurl_join(c->base_url, href, &msg_data.rfc5988_link.url);
|
|
||||||
|
|
||||||
xmlFree(href);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_data.rfc5988_link.rel = (char *)xmlGetProp(node,
|
|
||||||
(const xmlChar *)"rel");
|
|
||||||
msg_data.rfc5988_link.type = (char *)xmlGetProp(node,
|
|
||||||
(const xmlChar *)"type");
|
|
||||||
|
|
||||||
content_broadcast(&c->base, CONTENT_MSG_LINK, msg_data);
|
|
||||||
|
|
||||||
if (error == NSERROR_OK) {
|
|
||||||
nsurl_unref(msg_data.rfc5988_link.url);
|
|
||||||
}
|
|
||||||
if (msg_data.rfc5988_link.rel) {
|
|
||||||
xmlFree(msg_data.rfc5988_link.rel);
|
|
||||||
}
|
|
||||||
if (msg_data.rfc5988_link.type) {
|
|
||||||
xmlFree(msg_data.rfc5988_link.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user