about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorMarco Peereboom <marco@conformal.com>2011-01-12 18:35:23 +0000
committerMarco Peereboom <marco@conformal.com>2011-01-12 18:35:23 +0000
commita8cbdb9eaf9b3206dd7a477186a0400aba46dcb6 (patch)
treebbb28e14fd44f9d5fc3bdb73887aae74b538ba1d
parentcbe85217c4706f36cef8e27f2d9c89294b843a42 (diff)
downloadxombrero-a8cbdb9eaf9b3206dd7a477186a0400aba46dcb6.tar.gz
reshuffle favicon stuff to prevent some race conditions and intricacies'
-rw-r--r--xxxterm.c246
1 files changed, 134 insertions, 112 deletions
diff --git a/xxxterm.c b/xxxterm.c
index a947209..957a628 100644
--- a/xxxterm.c
+++ b/xxxterm.c
@@ -161,15 +161,18 @@ struct tab {
 	GtkWidget		*forward;
 	GtkWidget		*stop;
 	GtkWidget		*js_toggle;
-	GdkPixbuf		*icon_pixbuf;
 	guint			tab_id;
-	char			*icon_uri;
-	WebKitDownload		*icon_download;
 	WebKitWebView		*wv;
 
 	WebKitWebHistoryItem	*item;
 	WebKitWebBackForwardList	*bfl;
 
+	/* favicon */
+	WebKitNetworkRequest	*icon_request;
+	WebKitDownload		*icon_download;
+	GdkPixbuf		*icon_pixbuf;
+	gchar			*icon_dest_uri;
+
 	/* adjustments for browser */
 	GtkScrollbar		*sb_h;
 	GtkScrollbar		*sb_v;
@@ -561,51 +564,10 @@ int			updating_fl_tabs = 0;
 char			*global_search;
 uint64_t		blocked_cookies = 0;
 char			named_session[PATH_MAX];
-int			notify_icon_loaded_cb(WebKitWebView *, char *,
-			    struct tab *);
 void			update_favicon(struct tab *);
 int			icon_size_map(int);
 
 void
-check_favicon(struct tab *t)
-{
-	const gchar		*iconuri = webkit_web_view_get_icon_uri(t->wv);
-
-	DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon uri '%s'\n",
-	    __func__, t->tab_id, iconuri);
-
-	if (iconuri && strlen(iconuri) > 0)
-		notify_icon_loaded_cb(t->wv, (char *)iconuri, t);
-	else {
-		g_free(t->icon_uri);
-		t->icon_uri = NULL;
-		update_favicon(t);
-	}
-}
-
-void
-update_favicon(struct tab *t)
-{
-	DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon uri '%s'\n",
-	    __func__, t->tab_id, t->icon_uri);
-
-	if (t->icon_uri && strlen(t->icon_uri) > 0 && t->icon_pixbuf) {
-		gtk_entry_set_icon_from_pixbuf(GTK_ENTRY(t->uri_entry),
-		    GTK_ENTRY_ICON_PRIMARY, t->icon_pixbuf);
-		DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon uri '%s'"
-		    " (set)\n", __func__, t->tab_id,
-		    t->icon_uri ? t->icon_uri : "(NULL)");
-	} else {
-		gtk_entry_set_icon_from_icon_name(GTK_ENTRY(t->uri_entry),
-		    GTK_ENTRY_ICON_PRIMARY, "text-html");
-		DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon uri '%s'"
-		    " (!set)\n", __func__, t->tab_id,
-		    (t->icon_uri && strlen(t->icon_uri) > 0) ?
-		    t->icon_uri : "<empty>");
-	}
-}
-
-void
 load_webkit_string(struct tab *t, const char *str)
 {
 	/* we set this to indicate we want to manually do navaction */
@@ -4462,24 +4424,68 @@ done:
 }
 
 void
-load_favicon(struct tab *t)
+abort_and_free_favicon(struct tab *t)
+{
+	DNPRINTF(XT_D_DOWNLOAD, "%s: down %p req %p pix %p\n",
+	    __func__, t->icon_download, t->icon_request, t->icon_pixbuf);
+	if (t->icon_download) {
+		webkit_download_cancel(t->icon_download);
+		g_object_unref(t->icon_download);
+	}
+	if (t->icon_request)
+		g_object_unref(t->icon_request);
+	if (t->icon_pixbuf)
+		g_object_unref(t->icon_pixbuf);
+	if (t->icon_dest_uri)
+		g_free(t->icon_dest_uri);
+
+	t->icon_pixbuf = NULL;
+	t->icon_request = NULL;
+	t->icon_download = NULL;
+	t->icon_dest_uri = NULL;
+
+	gtk_entry_set_icon_from_icon_name(GTK_ENTRY(t->uri_entry),
+	    GTK_ENTRY_ICON_PRIMARY, "text-html");
+}
+
+void
+set_favicon_from_file(struct tab *t, char *file)
 {
-	gchar			*name_hash;
 	gint			width, height;
 	GdkPixbuf		*pixbuf, *scaled;
-	char			file[PATH_MAX];
+	struct stat		sb;
+
+	if (t == NULL || file == NULL)
+		return;
+	if (t->icon_pixbuf) {
+		DNPRINTF(XT_D_DOWNLOAD, "%s: icon already set\n", __func__);
+		return;
+	}
+
+	if (g_str_has_prefix(file, "file://"))
+		file += strlen("file://");
+	DNPRINTF(XT_D_DOWNLOAD, "%s: loading %s\n", __func__, file);
+
+	if (!stat(file, &sb)) {
+		if (sb.st_size == 0) {
+			/* corrupt icon so trash it */
+			DNPRINTF(XT_D_DOWNLOAD, "%s: corrupt icon %s\n",
+			    __func__, file);
+			unlink(file);
+			/* no need to set icon to default here */
+			return;
+		}
+	}
 
-	name_hash = g_compute_checksum_for_string(G_CHECKSUM_SHA256,
-	    t->icon_uri, -1);
-	snprintf(file, sizeof file, "%s/%s.ico", cache_dir, name_hash);
-	g_free(name_hash);
 	pixbuf = gdk_pixbuf_new_from_file(file, NULL);
-	if (!pixbuf) {
-		update_favicon(t);
+	if (pixbuf == NULL) {
+		gtk_entry_set_icon_from_icon_name(GTK_ENTRY(t->uri_entry),
+		    GTK_ENTRY_ICON_PRIMARY, "text-html");
 		return;
 	}
 
-	g_object_get(pixbuf, "width", &width, "height", &height, (char *)NULL);
+	g_object_get(pixbuf, "width", &width, "height", &height,
+	    (char *)NULL);
 	DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon size %dx%d\n",
 	    __func__, t->tab_id, width, height);
 
@@ -4490,15 +4496,15 @@ load_favicon(struct tab *t)
 	} else
 		scaled = pixbuf;
 
-	if (!scaled)
-		update_favicon(t);
-
-	if (t->icon_pixbuf)
-		g_object_unref(t->icon_pixbuf);
+	if (scaled == NULL) {
+		scaled = gdk_pixbuf_scale_simple(pixbuf, 16, 16,
+		    GDK_INTERP_BILINEAR);
+		return;
+	}
 
 	t->icon_pixbuf = scaled;
-
-	update_favicon(t);
+	gtk_entry_set_icon_from_pixbuf(GTK_ENTRY(t->uri_entry),
+	    GTK_ENTRY_ICON_PRIMARY, t->icon_pixbuf);
 }
 
 void
@@ -4507,78 +4513,95 @@ favicon_download_status_changed_cb(WebKitDownload *download, GParamSpec *spec,
 {
 	WebKitDownloadStatus	status = webkit_download_get_status (download);
 
+	if (t == NULL)
+		return;
+
+	DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d status %d\n",
+	    __func__, t->tab_id, status);
+
 	switch (status) {
-	case WEBKIT_DOWNLOAD_STATUS_FINISHED:
-		load_favicon(t);
-		g_object_unref(t->icon_download);
-		break;
 	case WEBKIT_DOWNLOAD_STATUS_ERROR:
+		/* -1 */
+		break;
+	case WEBKIT_DOWNLOAD_STATUS_CREATED:
+		/* 0 */
+		break;
+	case WEBKIT_DOWNLOAD_STATUS_STARTED:
+		/* 1 */
+		break;
 	case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
-		g_object_unref(t->icon_download);
+		/* 2 */
+		break;
+	case WEBKIT_DOWNLOAD_STATUS_FINISHED:
+		/* 3 */
+		DNPRINTF(XT_D_DOWNLOAD, "%s: setting icon to %s\n",
+		    __func__, t->icon_dest_uri);
+		set_favicon_from_file(t, t->icon_dest_uri);
+		g_free(t->icon_dest_uri);
+		/* these will be freed post callback */
+		t->icon_request = NULL;
+		t->icon_download = NULL;
+		t->icon_dest_uri = NULL;
 		break;
 	default:
 		break;
 	}
 }
 
-int
-notify_icon_loaded_cb(WebKitWebView *wv, char *uri, struct tab *t)
+void
+notify_icon_loaded_cb(WebKitWebView *wv, gchar *uri, struct tab *t)
 {
-	WebKitNetworkRequest	*request;
-	gchar			*name_hash, *dest_uri, file[PATH_MAX];
+	gchar			*name_hash, file[PATH_MAX];
 	struct stat		sb;
 
-	if (uri == NULL || t == NULL)
-		return (FALSE);
-
-	if (t->icon_uri) {
-		if (!strcmp(t->icon_uri, uri))
-			return (TRUE);
-		g_free(t->icon_uri);
-	}
+	DNPRINTF(XT_D_DOWNLOAD, "notify_icon_loaded_cb %s\n", uri);
 
-	t->icon_uri = g_strdup_printf("%s", uri);
-	DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon uri %s "
-	    "(dl!)\n", __func__, t->tab_id, uri);
-
-	if (t->icon_download && G_IS_OBJECT(t->icon_download)
-	    && WEBKIT_IS_DOWNLOAD(t->icon_download)) {
-		webkit_download_cancel(t->icon_download);
-		g_object_unref(t->icon_download);
-	}
+	if (uri == NULL || t == NULL)
+		return;
 
-	request = webkit_network_request_new(t->icon_uri);
-	if (!request) {
-		DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon uri %s "
-		"(request failed)\n", __func__, t->tab_id, uri);
-		return FALSE;
+	if (t->icon_request) {
+		DNPRINTF(XT_D_DOWNLOAD, "%s: download in progress\n", __func__);
+		return;
 	}
-	t->icon_download = webkit_download_new(request);
-	g_object_unref(request);
 
+	/* check to see if we got the icon in cache */
 	name_hash = g_compute_checksum_for_string(G_CHECKSUM_SHA256, uri, -1);
 	snprintf(file, sizeof file, "%s/%s.ico", cache_dir, name_hash);
 	g_free(name_hash);
+
 	if (!stat(file, &sb)) {
 		if (sb.st_size > 0) {
-			load_favicon(t);
-			return (TRUE);
+			DNPRINTF(XT_D_DOWNLOAD, "%s: loading from cache %s\n",
+			    __func__, file);
+			set_favicon_from_file(t, file);
+			return;
 		}
 
 		/* corrupt icon so trash it */
+		DNPRINTF(XT_D_DOWNLOAD, "%s: corrupt icon %s\n",
+		    __func__, file);
 		unlink(file);
 	}
 
-	dest_uri = g_strdup_printf("file://%s", file);
-	webkit_download_set_destination_uri(t->icon_download, dest_uri);
-	g_free(dest_uri);
+	/* create download for icon */
+	t->icon_request = webkit_network_request_new(uri);
+	if (t->icon_request == NULL) {
+		DNPRINTF(XT_D_DOWNLOAD, "%s: invalid uri %s\n",
+		    __func__, uri);
+		return;
+	}
 
-	g_signal_connect(G_OBJECT (t->icon_download), "notify::status",
-	    G_CALLBACK (favicon_download_status_changed_cb), t);
+	t->icon_download = webkit_download_new(t->icon_request);
 
-	webkit_download_start(t->icon_download);
+	/* we have to free icon_dest_uri later */
+	t->icon_dest_uri = g_strdup_printf("file://%s", file);
+	webkit_download_set_destination_uri(t->icon_download,
+	    t->icon_dest_uri);
 
-	return (TRUE);
+	g_signal_connect(G_OBJECT(t->icon_download), "notify::status",
+	    G_CALLBACK(favicon_download_status_changed_cb), t);
+
+	webkit_download_start(t->icon_download);
 }
 
 void
@@ -4598,6 +4621,7 @@ notify_load_status_cb(WebKitWebView* wview, GParamSpec* pspec, struct tab *t)
 
 	switch (webkit_web_view_get_load_status(wview)) {
 	case WEBKIT_LOAD_PROVISIONAL:
+		abort_and_free_favicon(t);
 #if GTK_CHECK_VERSION(2, 20, 0)
 		gtk_widget_show(t->spinner);
 		gtk_spinner_start(GTK_SPINNER(t->spinner));
@@ -4682,7 +4706,6 @@ notify_load_status_cb(WebKitWebView* wview, GParamSpec* pspec, struct tab *t)
 		gtk_widget_set_sensitive(GTK_WIDGET(t->stop), FALSE);
 		break;
 	}
-	check_favicon(t);
 
 	if (t->item)
 		gtk_widget_set_sensitive(GTK_WIDGET(t->backward), TRUE);
@@ -5333,6 +5356,7 @@ stop_cb(GtkWidget *w, struct tab *t)
 	}
 
 	webkit_web_frame_stop_loading(frame);
+	abort_and_free_favicon(t);
 }
 
 void
@@ -5454,6 +5478,10 @@ create_toolbar(struct tab *t)
 	gtk_box_pack_start(GTK_BOX(eb1), t->uri_entry, TRUE, TRUE, 0);
 	gtk_box_pack_start(GTK_BOX(b), eb1, TRUE, TRUE, 0);
 
+	/* set empty favicon */
+	gtk_entry_set_icon_from_icon_name(GTK_ENTRY(t->uri_entry),
+	    GTK_ENTRY_ICON_PRIMARY, "text-html");
+
 	/* search entry */
 	if (fancy_bar && search_string) {
 		GtkWidget *eb2;
@@ -5559,12 +5587,8 @@ delete_tab(struct tab *t)
 	TAILQ_REMOVE(&tabs, t, entry);
 
 	/* halt all webkit activity */
+	abort_and_free_favicon(t);
 	webkit_web_view_stop_loading(t->wv);
-	if (t->icon_download && G_IS_OBJECT(t->icon_download) &&
-	    WEBKIT_IS_DOWNLOAD(t->icon_download)) {
-		webkit_download_cancel(t->icon_download);
-		g_object_unref(t->icon_download);
-	}
 	undo_close_tab_save(t);
 
 	gtk_widget_destroy(t->vbox);
@@ -5765,10 +5789,8 @@ create_new_tab(char *title, struct undo *u, int focus)
 
 	if (load)
 		webkit_web_view_load_uri(t->wv, title);
-	else {
+	else
 		gtk_widget_grab_focus(GTK_WIDGET(t->uri_entry));
-		check_favicon(t);
-	}
 
 	t->bfl = webkit_web_view_get_back_forward_list(t->wv);
 	/* restore the tab's history */