From 52ad2c1e2523b28aa5363656fbbef20e97665cce Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 6 Oct 2011 23:31:55 +0000 Subject: initial favicon support svn path=/trunk/netsurf/; revision=12975 --- content/content.h | 8 +++- desktop/browser.c | 123 +++++++++++++++++++++++++++++++++++++++++++----------- desktop/browser.h | 3 ++ gtk/scaffolding.c | 9 +--- render/html.c | 45 +++++++++++++------- render/html.h | 1 - 6 files changed, 139 insertions(+), 50 deletions(-) diff --git a/content/content.h b/content/content.h index b288cb61e..eb8fbe689 100644 --- a/content/content.h +++ b/content/content.h @@ -72,7 +72,7 @@ typedef enum { CONTENT_MSG_REDRAW, /**< needs redraw (eg. new animation frame) */ CONTENT_MSG_REFRESH, /**< wants refresh */ CONTENT_MSG_DOWNLOAD, /**< download, not for display */ - CONTENT_MSG_FAVICON_REFRESH, /**< favicon has been refreshed (eg. new animation frame) */ + CONTENT_MSG_LINK, /**< RFC5988 link */ } content_msg; /** Extra data for some content_msg messages. */ @@ -96,6 +96,12 @@ union content_msg_data { bool background; /** Low-level cache handle, for CONTENT_MSG_DOWNLOAD */ struct llcache_handle *download; + /** rfc5988 link data CONTENT_MSG_RFC5988_LINK */ + struct { + nsurl *url; + char *rel; + char *type; + } rfc5988_link; }; diff --git a/desktop/browser.c b/desktop/browser.c index fbcac5297..ed1cfc345 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -80,7 +80,6 @@ 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); 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, @@ -878,6 +877,34 @@ void browser_window_go_post(struct browser_window *bw, const char *url, nsurl_unref(nsref); } +/** + * Callback for fetchcache() for browser window favicon fetches. + */ + +static nserror browser_window_favicon_callback(hlcache_handle *c, + const hlcache_event *event, void *pw) +{ + struct browser_window *bw = pw; + + switch (event->type) { + case CONTENT_MSG_DONE: + LOG(("favicon contents for %p done!", bw)); + /* content_get_bitmap on the bw->favicon should give + us the favicon at this point + */ + if (bw->window != NULL) { + gui_window_set_icon(bw->window, bw->favicon); + } else { + LOG(("null browser window on favicon!")); + } + break; + + default: + LOG(("favicon unhandled event")); + break; + } + return NSERROR_OK; +} /** * Callback for fetchcache() for browser window fetches. @@ -935,6 +962,18 @@ nserror browser_window_callback(hlcache_handle *c, 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->loading_content = NULL; @@ -1001,7 +1040,32 @@ nserror browser_window_callback(hlcache_handle *c, browser_window_update(bw, false); browser_window_set_status(bw, content_get_status_message(c)); browser_window_stop_throbber(bw); - browser_window_set_icon(bw); + if (bw->favicon == NULL) { + /* 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); hotlist_visited(c); @@ -1078,12 +1142,27 @@ nserror browser_window_callback(hlcache_handle *c, bw->refresh_interval = event->data.delay * 100; break; - case CONTENT_MSG_FAVICON_REFRESH: - /* Cause the GUI to update */ - if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) { - gui_window_set_icon(bw->window, - html_get_favicon(bw->current_content)); + case CONTENT_MSG_LINK: /* content has an rfc5988 link element */ + { + nsurl *nsref = NULL; + if ((bw->favicon == NULL) && + (strstr(event->data.rfc5988_link.rel, "icon") != NULL)) { + /* its a favicon start a fetch for it */ + LOG(("fetching favicon rel:%s '%s'", + event->data.rfc5988_link.rel, + nsurl_access(event->data.rfc5988_link.url))); + hlcache_handle_retrieve(event->data.rfc5988_link.url, + HLCACHE_RETRIEVE_MAY_DOWNLOAD | + HLCACHE_RETRIEVE_SNIFF_TYPE, + nsref, + NULL, + browser_window_favicon_callback, + bw, + NULL, + CONTENT_IMAGE, + &bw->favicon); } + } break; default: @@ -1273,24 +1352,6 @@ bool browser_window_check_throbber(struct browser_window *bw) return false; } -/** - * when ready, set icon at top level - * \param bw browser_window - * current implementation ignores lower-levels' link rels completely - */ -void browser_window_set_icon(struct browser_window *bw) -{ - while (bw->parent) - bw = bw->parent; - - if (bw->current_content != NULL && - content_get_type(bw->current_content) == CONTENT_HTML) - gui_window_set_icon(bw->window, - html_get_favicon(bw->current_content)); - else - gui_window_set_icon(bw->window, NULL); -} - /** * Redraw browser window, set extent to content, and update title. * @@ -1663,6 +1724,18 @@ void browser_window_destroy_internal(struct browser_window *bw) bw->current_content = NULL; } + 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; + } + if (bw->box != NULL) { bw->box->iframe = NULL; bw->box = NULL; diff --git a/desktop/browser.h b/desktop/browser.h index d7d996c5e..c96c4f177 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -75,6 +75,9 @@ struct browser_window { /** Page being loaded, or 0. */ struct hlcache_handle *loading_content; + /** Page Favicon */ + struct hlcache_handle *favicon; + /** Window history structure. */ struct history *history; diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c index 5c0366c08..b9a4b0909 100644 --- a/gtk/scaffolding.c +++ b/gtk/scaffolding.c @@ -2254,14 +2254,9 @@ void nsgtk_scaffolding_set_top_level (struct gui_window *gw) nsgtk_search_set_forward_state(true, bw); nsgtk_search_set_back_state(true, bw); - /* Ensure the window's title bar as well as favicon are updated */ + /* Ensure the window's title bar is updated */ if (bw->current_content != NULL) { - gui_window_set_title(gw, - content_get_title(bw->current_content)); - - if (content_get_type(bw->current_content) == CONTENT_HTML) - gui_window_set_icon(gw, - html_get_favicon(bw->current_content)); + gui_window_set_title(gw, content_get_title(bw->current_content)); } } diff --git a/render/html.c b/render/html.c index 93b34cafb..4c08a6620 100644 --- a/render/html.c +++ b/render/html.c @@ -810,6 +810,35 @@ bool html_head(html_content *c, xmlNode *head) } xmlFree(s); } + } else if (strcmp((const char *) node->name, "link") == 0) { + union content_msg_data msg_data; + 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; @@ -2384,22 +2413,6 @@ struct content_html_object *html_get_objects(hlcache_handle *h, unsigned int *n) return c->object_list; } -/** - * Retrieve favicon associated with an HTML document - * - * \param h HTML document to retrieve favicon from - * \return Pointer to favicon, or NULL if none - */ -hlcache_handle *html_get_favicon(hlcache_handle *h) -{ - html_content *c = (html_content *) hlcache_handle_get_content(h); - - assert(c != NULL); - - return NULL; -} - - /** * Retrieve layout coordinates of box with given id * diff --git a/render/html.h b/render/html.h index 648c9751f..dba1ce427 100644 --- a/render/html.h +++ b/render/html.h @@ -169,7 +169,6 @@ struct html_stylesheet *html_get_stylesheets(struct hlcache_handle *h, unsigned int *n); struct content_html_object *html_get_objects(struct hlcache_handle *h, unsigned int *n); -struct hlcache_handle *html_get_favicon(struct hlcache_handle *h); bool html_get_id_offset(struct hlcache_handle *h, const char *frag_id, int *x, int *y); -- cgit v1.2.3