Index: src/file-manager/fm-directory-view.c
===================================================================
--- src/file-manager/fm-directory-view.c	(revision 13961)
+++ src/file-manager/fm-directory-view.c	(working copy)
@@ -8374,95 +8374,36 @@ ask_link_action (FMDirectoryView *view)
 	return result;
 }
 
-void
-fm_directory_view_handle_netscape_url_drop (FMDirectoryView  *view,
-					    const char       *encoded_url,
-					    const char       *target_uri,
-					    GdkDragAction     action,
-					    int               x,
-					    int               y)
-{
-	GdkPoint point;
-	GdkScreen *screen;
-	int screen_num;
-	char *url, *title;
-	char *link_name, *link_display_name;
+typedef struct {
+	FMDirectoryView *view;
+	GdkDragAction action;
+	char *title;
+	char *url;
+	char *target_uri;
 	char *container_uri;
-	GArray *points;
-	char **bits;
-	GList *uri_list = NULL;
-	GFile *f;
-
-	if (encoded_url == NULL) {
-		return;
-	}
-
-	container_uri = NULL;
-	if (target_uri == NULL) {
-		container_uri = fm_directory_view_get_backing_uri (view);
-		g_assert (container_uri != NULL);
-	}
-
-	f = g_file_new_for_uri (target_uri != NULL ? target_uri : container_uri);
-	if (!g_file_is_native (f)) {
-		eel_show_warning_dialog (_("Drag and drop is not supported."),
-					 _("Drag and drop is only supported on local file systems."),
-					 fm_directory_view_get_containing_window (view));
-		g_object_unref (f);
-		g_free (container_uri);
-		return;
-	}
-	g_object_unref (f);
-
-	/* _NETSCAPE_URL_ works like this: $URL\n$TITLE */
-	bits = g_strsplit (encoded_url, "\n", 0);
-	switch (g_strv_length (bits)) {
-	case 0:
-		g_strfreev (bits);
-		g_free (container_uri);
-		return;
-	case 1:
-		url = bits[0];
-		title = NULL;
-		break;
-	default:
-		url = bits[0];
-		title = bits[1];
-	}
-
-	if (action == GDK_ACTION_ASK) {
-		GFileInfo *info;
-		GFile *f;
-		const char *mime_type;
-
-		f = g_file_new_for_uri (url);
-		info = g_file_query_info (f, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, 0, NULL, NULL);
-		mime_type = NULL;
-
-		if (info) {
-			mime_type = g_file_info_get_content_type (info);
-		}
+	int x;
+	int y;
+} UrlDropData;
 
-		if (mime_type != NULL &&
-		    (g_content_type_equals (mime_type, "text/html") ||
-		     g_content_type_equals (mime_type, "text/xml")  ||
-		     g_content_type_equals (mime_type, "application/xhtml+xml"))) {
-			action = GDK_ACTION_LINK;
-		} else if (mime_type != NULL &&
-			   g_content_type_equals (mime_type, "text/plain")) {
-			action = ask_link_action (view);
-		} else {
-			action = GDK_ACTION_COPY;
-		}
-		if (info) {
-			g_object_unref (info);
-		}
+static void
+url_drop_data_free (UrlDropData *data)
+{
+	g_free (data->url);
+	g_free (data->title);
+	g_free (data->container_uri);
+	g_free (data->target_uri);
+	
+	g_slice_free (UrlDropData, data);
+}
 
-		if (action == 0) {
-			g_free (container_uri);
-			return;
-		}
-	}
+static void 
+finish_handling_netscape_url_drop (UrlDropData *data)
+{
+	GdkDragAction action;
+	FMDirectoryView *view;
+	
+	action = data->action;
+	view = data->view;
 
 	/* We don't support GDK_ACTION_ASK or GDK_ACTION_PRIVATE
 	 * and we don't support combinations either. */
@@ -8473,39 +8414,47 @@ fm_directory_view_handle_netscape_url_dr
 		eel_show_warning_dialog (_("Drag and drop is not supported."),
 					 _("An invalid drag type was used."),
 					 fm_directory_view_get_containing_window (view));
-		g_free (container_uri);
+		url_drop_data_free (data);
 		return;
 	}
 
 	if (action == GDK_ACTION_LINK) {
-		if (eel_str_is_empty (title)) {
+		char *link_name;
+		
+		if (eel_str_is_empty (data->title)) {
 			GFile *f;
 
-			f = g_file_new_for_uri (url);
+			f = g_file_new_for_uri (data->url);
 			link_name = g_file_get_basename (f);
 			g_object_unref (f);
 		} else {
-			link_name = g_strdup (title);
+			link_name = g_strdup (data->title);
 		}
 		
 		if (!eel_str_is_empty (link_name)) {
+			char *link_display_name;
+			GdkPoint point;
+			GdkScreen *screen;
+			int screen_num;
+			
 			link_display_name = g_strdup_printf (_("Link to %s"), link_name);
 
 			/* The filename can't contain slashes, strip em.
 			   (the basename of http://foo/ is http://foo/) */
 			revert_slashes (link_name);
 
-			point.x = x;
-			point.y = y;
+			point.x = data->x;
+			point.y = data->y;
 
 			screen = gtk_widget_get_screen (GTK_WIDGET (view));
 			screen_num = gdk_screen_get_number (screen);
 
-			nautilus_link_local_create (target_uri != NULL ? target_uri : container_uri,
+			nautilus_link_local_create (data->target_uri != NULL ?
+						    data->target_uri : data->container_uri,
 						    link_name,
 						    link_display_name,
 						    "gnome-fs-bookmark",
-						    url,
+						    data->url,
 						    &point,
 						    screen_num,
 						    TRUE);
@@ -8514,25 +8463,156 @@ fm_directory_view_handle_netscape_url_dr
 		}
 		g_free (link_name);
 	} else {
+		GArray *points;
+		GList *uri_list;
 		GdkPoint tmp_point = { 0, 0 };
 
+		uri_list = NULL;
+
 		/* pass in a 1-item array of icon positions, relative to x, y */
 		points = g_array_new (FALSE, TRUE, sizeof (GdkPoint));
 		g_array_append_val (points, tmp_point);
 
-		uri_list = g_list_append (uri_list, url);
+		uri_list = g_list_append (uri_list, data->url);
 
 		fm_directory_view_move_copy_items (uri_list, points,
-						   target_uri != NULL ? target_uri : container_uri,
-						   action, x, y, view);
+						   data->target_uri != NULL ?
+						   data->target_uri : data->container_uri,
+						   action, data->x, data->y, view);
 
 		g_list_free (uri_list);
 		g_array_free (points, TRUE);
 	}
+	
+	url_drop_data_free (data);
+}
+
+static void
+query_info_callback (GFile *file,
+		     GAsyncResult *res,
+		     UrlDropData *data)
+{
+	FMDirectoryView *view;
+	GdkDragAction action;
+	GFileInfo *info;
+	GError *error;
+	const char *mime_type;
+	
+	mime_type = NULL;
+	error = NULL;
+	view = data->view;
+
+	info = g_file_query_info_finish (file, res, &error);
+
+	if (info) {
+		mime_type = g_file_info_get_content_type (info);
+	}
+
+	if (mime_type != NULL &&
+	    (g_content_type_equals (mime_type, "text/html") ||
+	     g_content_type_equals (mime_type, "text/xml")  ||
+	     g_content_type_equals (mime_type, "application/xhtml+xml"))) {
+		action = GDK_ACTION_LINK;
+	} else if (mime_type != NULL &&
+		   g_content_type_equals (mime_type, "text/plain")) {
+		action = ask_link_action (view);
+	} else if (mime_type == NULL) {
+		/* We were not able to query info on the dropped uri,
+		 * so it's very likely we won't be able to copy it.
+		 */
+		action = GDK_ACTION_LINK;
+	} else {
+		/* mime_type != NULL and content type isn't html neither
+		 * plain text.
+		 */
+		action = GDK_ACTION_COPY;
+	}
+	if (info) {
+		g_object_unref (info);
+	}
 
+	if (action == 0) {
+		return;
+	} else {
+		data->action = action;
+		finish_handling_netscape_url_drop (data);
+	}
+}
+
+void
+fm_directory_view_handle_netscape_url_drop (FMDirectoryView  *view,
+					    const char       *encoded_url,
+					    const char       *target_uri,
+					    GdkDragAction     action,
+					    int               x,
+					    int               y)
+{
+	UrlDropData *data;
+	char *url, *title;
+	char *container_uri;
+	char **bits;
+	GFile *f;
+
+	if (encoded_url == NULL) {
+		return;
+	}
+	
+	container_uri = NULL;
+	if (target_uri == NULL) {
+		container_uri = fm_directory_view_get_backing_uri (view);
+		g_assert (container_uri != NULL);
+	}
+
+	f = g_file_new_for_uri (target_uri != NULL ? target_uri : container_uri);
+	if (!g_file_is_native (f)) {
+		eel_show_warning_dialog (_("Drag and drop is not supported."),
+					 _("Drag and drop is only supported on local file systems."),
+					 fm_directory_view_get_containing_window (view));
+		g_object_unref (f);
+		g_free (container_uri);
+		return;
+	}
+	g_object_unref (f);
+
+	/* _NETSCAPE_URL_ works like this: $URL\n$TITLE */
+	bits = g_strsplit (encoded_url, "\n", 0);
+	switch (g_strv_length (bits)) {
+	case 0:
+		g_strfreev (bits);
+		g_free (container_uri);
+		return;
+	case 1:
+		url = g_strdup (bits[0]);
+		title = NULL;
+		break;
+	default:
+		url = g_strdup (bits[0]);
+		title = g_strdup (bits[1]);
+	}
 	g_strfreev (bits);
+	
+	data = g_slice_new0 (UrlDropData);
+	data->view = view;
+	data->action = action;
+	data->title = title;
+	data->url = url;
+	data->target_uri = g_strdup (target_uri);
+	data->container_uri = container_uri;
+	data->x = x;
+	data->y = y;
 
-	g_free (container_uri);
+	if (action == GDK_ACTION_ASK) {
+		GFile *f;
+
+		f = g_file_new_for_uri (url);
+		g_file_query_info_async (f,
+					 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+					 0, G_PRIORITY_DEFAULT, NULL,
+					 (GAsyncReadyCallback) query_info_callback, data);
+		return;
+	} else {
+		finish_handling_netscape_url_drop (data);
+	}
 }
 
 void
