Index: libnautilus-private/nautilus-file-private.h
===================================================================
--- libnautilus-private/nautilus-file-private.h	(revision 13646)
+++ libnautilus-private/nautilus-file-private.h	(working copy)
@@ -140,6 +140,12 @@
 	/* Mount for mountpoint or the references GMount for a "mountable" */
 	GMount *mount;
 	
+	/* The mount icon has been found for this file, or NULL.
+	 * Does not use ->icon, because nautilus_file_get_gicon() assumes
+	 * that is a themed icon
+	**/
+	GIcon *mount_icon;
+	
 	/* boolean fields: bitfield to save space, since there can be
            many NautilusFile objects. */
 
@@ -205,6 +211,9 @@
 	eel_boolean_bit can_mount                     : 1;
 	eel_boolean_bit can_unmount                   : 1;
 	eel_boolean_bit can_eject                     : 1;
+	
+	/* TRUE if a search for a mount icon has been performed */
+	eel_boolean_bit searched_for_mount_icon       : 1;
 };
 
 typedef struct {
Index: libnautilus-private/nautilus-file.c
===================================================================
--- libnautilus-private/nautilus-file.c	(revision 13646)
+++ libnautilus-private/nautilus-file.c	(working copy)
@@ -318,6 +318,12 @@
 		file->details->icon = NULL;
 	}
 
+	if (file->details->mount_icon != NULL) {
+		g_object_unref (file->details->mount_icon);
+		file->details->mount_icon = NULL;
+	}
+	file->details->searched_for_mount_icon = FALSE;
+
 	g_free (file->details->thumbnail_path);
 	file->details->thumbnail_path = NULL;
 	file->details->thumbnailing_failed = FALSE;
@@ -654,6 +660,9 @@
 	if (file->details->icon) {
 		g_object_unref (file->details->icon);
 	}
+	if (file->details->mount_icon) {
+		g_object_unref (file->details->mount_icon);
+	}
 	g_free (file->details->thumbnail_path);
 	g_free (file->details->symlink_name);
 	eel_ref_str_unref (file->details->mime_type);
@@ -3287,6 +3296,177 @@
 	return g_themed_icon_new ("text-x-generic");
 }
 
+typedef struct _MountIconSearchData
+{
+	NautilusFile *mount_file;
+	GFile *volume_root;
+	GFile *autorun_path;
+} MountIconSearchData;
+
+static void
+on_icon_file_located (GObject *source_object, GAsyncResult *res,
+                      gpointer user_data)
+{
+	GFile *icon_file;
+	MountIconSearchData *data = (MountIconSearchData *) (user_data);
+	NautilusFile *mount_file = data->mount_file;
+	
+	icon_file = nautilus_find_file_insensitive_finish (G_FILE (source_object),
+	                                                   res, NULL);
+	
+	g_return_if_fail (G_IS_OBJECT (data->volume_root));
+	g_return_if_fail (G_IS_FILE (data->volume_root));
+	g_return_if_fail (NAUTILUS_IS_FILE (data->mount_file));
+	
+	if (G_IS_FILE (icon_file))
+	{
+		mount_file->details->mount_icon = g_file_icon_new (icon_file);
+		mount_file->details->searched_for_mount_icon = TRUE;
+		g_return_if_fail (G_IS_OBJECT (icon_file));
+		g_object_unref (icon_file);
+		nautilus_file_changed (mount_file);
+	}
+	if (data->volume_root) g_object_unref (data->volume_root);
+	g_free (data);
+}
+
+static void
+on_autorun_loaded (GObject *source_object, GAsyncResult *res,
+                   gpointer user_data)
+{
+	gchar *content, *relative_icon_path = NULL;
+	gsize content_length;
+	MountIconSearchData *data = (MountIconSearchData *) (user_data);
+	
+	if (g_file_load_contents_finish (data->autorun_path, res, &content,
+	                                 &content_length, NULL, NULL))
+	{
+		/* Scan through for an "icon=" line. Can't use GKeyFile,
+		 * because .inf files aren't always valid key files
+		**/
+		GRegex *icon_regex;
+		GMatchInfo *match_info;
+		
+		/* [^,] is because sometimes the icon= line
+		 * has a comma at the end
+		**/
+		icon_regex = g_regex_new ("icon=([^,\\r\\n]+)",
+		                          G_REGEX_CASELESS, 0, NULL);
+		g_regex_match (icon_regex, content, 0,
+		               &match_info);
+		
+		/* Even if there are multiple matches, pick only the
+		 * first.
+		**/
+		if (g_match_info_matches (match_info))
+		{
+			gchar *chr;
+			gchar *word = g_match_info_fetch (match_info, 1);
+			
+			/* Replace '\' with '/' */
+			while ((chr = strchr (word, '\\')) != NULL)
+				*chr = '/';
+			
+			/* If the file name's not valid UTF-8,
+			 * don't even try to load it
+			**/
+			if (g_utf8_validate (word, -1, NULL))
+				relative_icon_path = word;
+			else
+				g_free (word);
+		}
+		
+		g_match_info_free (match_info);
+		
+		g_regex_unref (icon_regex);
+		g_free (content);
+	}
+	
+	g_object_unref (data->autorun_path);
+	data->autorun_path = NULL;
+	
+	if (relative_icon_path)
+	{
+		nautilus_find_file_insensitive_async (data->volume_root,
+		                                      relative_icon_path,
+		                                      NULL, on_icon_file_located,
+		                                      data);
+		
+		g_free (relative_icon_path);
+	}
+	
+	else
+	{
+		data->mount_file->details->searched_for_mount_icon = TRUE;
+		g_object_unref (data->volume_root);
+		g_free (data);
+	}
+}
+
+static void
+on_autorun_located (GObject *source_object, GAsyncResult *res,
+                    gpointer user_data)
+{
+	GFile *autorun_path;
+	MountIconSearchData *data = (MountIconSearchData *) (user_data);
+	
+	autorun_path = nautilus_find_file_insensitive_finish (G_FILE (source_object),
+	                                                      res, NULL);
+	data->autorun_path = autorun_path;
+	g_file_load_contents_async (autorun_path, NULL, on_autorun_loaded, data);
+}
+
+static GIcon *
+nautilus_find_cdrom_icon (NautilusFile *file)
+{
+	GIcon *icon = NULL;
+	gchar *root_uri;
+	gboolean is_mount = FALSE;
+	MountIconSearchData *search_data;
+	
+	/* If the file already has a mount icon, return it. Otherwise,
+	 * start an async search for the icon
+	**/
+	if (file->details->searched_for_mount_icon)
+	{
+		if (file->details->mount_icon)
+		{
+			g_object_ref (file->details->mount_icon);
+			return file->details->mount_icon;
+		}
+		return NULL;
+	}
+	
+	if (file->details->mount && file->details->activation_location)
+	{
+		GFile *mount_root = g_mount_get_root (file->details->mount);
+		is_mount = g_file_equal (mount_root, file->details->activation_location);
+		g_object_unref (mount_root);
+	}
+	
+	/* If this file is not a mount, there's no need to search */
+	if (!is_mount)
+	{
+		file->details->searched_for_mount_icon = TRUE;
+		return NULL;
+	}
+	
+	search_data = g_new (MountIconSearchData, 1);
+	search_data->mount_file = g_object_ref (file);
+	
+	/* Find the mount point of the volume */
+	root_uri = nautilus_file_get_activation_uri (file);
+	search_data->volume_root = g_file_new_for_uri (root_uri);
+	g_free (root_uri);
+	
+	nautilus_find_file_insensitive_async (search_data->volume_root,
+	                                      "autorun.inf",
+	                                      NULL, on_autorun_located,
+	                                      search_data);
+	
+	return icon;
+}
+
 NautilusIconInfo *
 nautilus_file_get_icon (NautilusFile *file,
 			int size,
@@ -3367,6 +3547,13 @@
 		}
 	}
 
+	if ((gicon = nautilus_find_cdrom_icon (file)))
+	{
+		icon = nautilus_icon_info_lookup (gicon, size);
+		g_object_unref (gicon);
+		return icon;
+	}
+	
 	if (file->details->is_thumbnailing &&
 	    flags & NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS)
 		gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING);
Index: libnautilus-private/nautilus-file-utilities.c
===================================================================
--- libnautilus-private/nautilus-file-utilities.c	(revision 13646)
+++ libnautilus-private/nautilus-file-utilities.c	(working copy)
@@ -48,11 +48,20 @@
 #define LEGACY_DESKTOP_DIRECTORY_NAME ".gnome-desktop"
 #define DEFAULT_DESKTOP_DIRECTORY_MODE (0755)
 
+#define INSENSITIVE_SEARCH_ITEMS_PER_CALLBACK 100
+
 static void update_xdg_dir_cache (void);
 static void schedule_user_dirs_changed (void);
 static void desktop_dir_changed (void);
 
+static void
+enumerated_children_callback (GObject *source_object, GAsyncResult *res,
+                              gpointer user_data);
 
+static void
+more_files_callback (GObject *source_object, GAsyncResult *res,
+                     gpointer user_data);
+
 char *
 nautilus_compute_title_for_location (GFile *location)
 {
@@ -844,6 +853,243 @@
 	return location;
 }
 
+typedef struct _InsensitiveFileSearchData
+{
+	GFile *root;
+	gchar *original_path;
+	gchar **split_path;
+	gint index;
+	GFileEnumerator *enumerator;
+	GFile *current_file;
+	
+	GCancellable *cancellable;
+	GAsyncReadyCallback callback;
+	gpointer user_data;
+} InsensitiveFileSearchData;
+
+void
+nautilus_find_file_insensitive_async (GFile              *parent,
+                                      const gchar        *name,
+                                      GCancellable       *cancellable,
+                                      GAsyncReadyCallback callback,
+                                      gpointer            user_data)
+{
+	InsensitiveFileSearchData *data;
+	
+	g_return_if_fail (g_utf8_validate (name, -1, NULL));
+	
+	data = g_new (InsensitiveFileSearchData, 1);
+	data->root = g_object_ref (parent);
+	data->original_path = g_strdup (name);
+	data->split_path = g_regex_split_simple (G_DIR_SEPARATOR_S, name, 0, 0);
+	data->index = 0;
+	data->enumerator = NULL;
+	data->current_file = g_object_ref (parent);
+	data->cancellable = cancellable;
+	data->callback = callback;
+	data->user_data = user_data;
+	
+	g_file_enumerate_children_async (data->current_file,
+	                                 G_FILE_ATTRIBUTE_STANDARD_NAME,
+	                                 0, G_PRIORITY_DEFAULT, cancellable,
+	                                 enumerated_children_callback, data);
+}
+
+static void
+clear_find_file_insensitive_state (InsensitiveFileSearchData *data)
+{
+	if (data->root) g_object_unref (data->root);
+	if (data->original_path) g_free (data->original_path);
+	if (data->split_path) g_strfreev (data->split_path);
+	if (data->enumerator) g_object_unref (data->enumerator);
+	if (data->current_file) g_object_unref (data->current_file);
+	g_free (data);
+}
+
+static void
+enumerated_children_callback (GObject *source_object, GAsyncResult *res,
+                              gpointer user_data)
+{
+	GFileEnumerator *enumerator;
+	GError *error = NULL;
+	InsensitiveFileSearchData *data = (InsensitiveFileSearchData *) (user_data);
+	
+	enumerator = g_file_enumerate_children_finish (G_FILE (source_object),
+	                                               res, &error);
+	
+	if (error) g_error_free (error);
+	if (enumerator == NULL)
+	{
+		GSimpleAsyncResult *simple;
+		GFile *file;
+		
+		simple = g_simple_async_result_new (G_OBJECT (data->root),
+		                                    data->callback,
+		                                    data->user_data,
+		                                    nautilus_find_file_insensitive_async);
+		
+		file = g_file_get_child (data->root, data->original_path);
+		
+		g_simple_async_result_set_op_res_gpointer (simple, g_object_ref (file), g_object_unref);
+		g_simple_async_result_complete_in_idle (simple);
+		g_object_unref (simple);
+		clear_find_file_insensitive_state (data);
+		return;
+	}
+	
+	data->enumerator = enumerator;
+	g_file_enumerator_next_files_async (enumerator,
+	                                    INSENSITIVE_SEARCH_ITEMS_PER_CALLBACK,
+	                                    G_PRIORITY_DEFAULT,
+	                                    data->cancellable,
+	                                    more_files_callback,
+	                                    data);
+}
+
+static void
+more_files_callback (GObject *source_object, GAsyncResult *res,
+                     gpointer user_data)
+{
+	InsensitiveFileSearchData *data = (InsensitiveFileSearchData *) (user_data);
+	GList *files, *l;
+	gchar *filename = NULL, *component, *case_folded_name,
+	      *name_collation_key;
+	GError *error = NULL;
+	gboolean end_of_files;
+	
+	files = g_file_enumerator_next_files_finish (data->enumerator,
+	                                             res, &error);
+	
+	end_of_files = (g_list_length (files) < INSENSITIVE_SEARCH_ITEMS_PER_CALLBACK);
+	
+	component = data->split_path[data->index];
+	g_return_if_fail (component != NULL);
+	
+	case_folded_name = g_utf8_casefold (component, -1);
+	name_collation_key = g_utf8_collate_key (case_folded_name, -1);
+	g_free (case_folded_name);
+	
+	for (l = files; l != NULL; l = l->next)
+	{
+		GFileInfo *info;
+		const gchar *this_name;
+		
+		info = l->data;
+		this_name = g_file_info_get_name (info);
+		
+		if (g_utf8_validate (this_name, -1, NULL))
+		{
+			gchar *case_folded, *key;
+			case_folded = g_utf8_casefold (this_name, -1);
+			key = g_utf8_collate_key (case_folded, -1);
+			g_free (case_folded);
+			
+			if (strcmp (key, name_collation_key) == 0)
+				filename = g_strdup (this_name);
+			g_free (key);
+		}
+		g_object_unref (info);
+		if (filename)
+			break;
+	}
+	
+	if (error) g_error_free (error);
+	g_list_free (files);
+	g_free (name_collation_key);
+	
+	if (filename)
+	{
+		GFile *next_file;
+		
+		g_object_unref (data->enumerator);
+		data->enumerator = NULL;
+		
+		/* Set the current file and continue searching */
+		next_file = g_file_get_child (data->current_file, filename);
+		g_free (filename);
+		g_object_unref (data->current_file);
+		data->current_file = next_file;
+		data->index++;
+		
+		if (!data->split_path[data->index])
+		{
+			/* Search is complete, file was found */
+			GSimpleAsyncResult *simple;
+			GFile *file = g_object_ref (data->current_file);
+			
+			simple = g_simple_async_result_new (G_OBJECT (data->root),
+			                                    data->callback,
+			                                    data->user_data,
+			                                    nautilus_find_file_insensitive_async);
+			
+			g_simple_async_result_set_op_res_gpointer (simple, g_object_ref (file), g_object_unref);
+			g_simple_async_result_complete_in_idle (simple);
+			g_object_unref (simple);
+			clear_find_file_insensitive_state (data);
+			return;
+		}
+		
+		/* Continue searching down the tree */
+		g_file_enumerate_children_async (data->current_file,
+		                                 G_FILE_ATTRIBUTE_STANDARD_NAME,
+		                                 0, G_PRIORITY_DEFAULT,
+		                                 data->cancellable,
+		                                 enumerated_children_callback,
+		                                 data);
+		return;
+	}
+	
+	if (end_of_files)
+	{
+		/* Could not find the given file, abort the search */
+		GSimpleAsyncResult *simple;
+		GFile *file;
+		
+		g_object_unref (data->enumerator);
+		data->enumerator = NULL;
+		
+		simple = g_simple_async_result_new (G_OBJECT (data->root),
+		                                    data->callback,
+		                                    data->user_data,
+		                                    nautilus_find_file_insensitive_async);
+		
+		file = g_file_get_child (data->root, data->original_path);
+		
+		g_simple_async_result_set_op_res_gpointer (simple, g_object_ref (file), g_object_unref);
+		g_simple_async_result_complete_in_idle (simple);
+		g_object_unref (simple);
+		clear_find_file_insensitive_state (data);
+		return;
+	}
+	
+	/* Continue enumerating */
+	g_file_enumerator_next_files_async (data->enumerator,
+	                                    INSENSITIVE_SEARCH_ITEMS_PER_CALLBACK,
+	                                    G_PRIORITY_DEFAULT,
+	                                    data->cancellable,
+	                                    more_files_callback,
+	                                    data);
+}
+
+GFile *
+nautilus_find_file_insensitive_finish (GFile        *parent,
+                                       GAsyncResult *result,
+                                       GError      **error)
+{
+	GSimpleAsyncResult *simple;
+	GFile *file;
+	
+	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+	
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	
+	if (g_simple_async_result_propagate_error (simple, error))
+		return NULL;
+	
+	file = G_FILE (g_simple_async_result_get_op_res_gpointer (simple));
+	return file;
+}
+
 #if !defined (NAUTILUS_OMIT_SELF_CHECK)
 
 void
Index: libnautilus-private/nautilus-file-utilities.h
===================================================================
--- libnautilus-private/nautilus-file-utilities.h	(revision 13646)
+++ libnautilus-private/nautilus-file-utilities.h	(working copy)
@@ -90,4 +90,16 @@
 
 GFile *  nautilus_find_existing_uri_in_hierarchy     (GFile *location);
 
+void
+nautilus_find_file_insensitive_async (GFile              *parent,
+                                      const gchar        *name,
+                                      GCancellable       *cancellable,
+                                      GAsyncReadyCallback callback,
+                                      gpointer            user_data);
+
+GFile *
+nautilus_find_file_insensitive_finish (GFile        *parent,
+                                       GAsyncResult *res,
+                                       GError      **error);
+
 #endif /* NAUTILUS_FILE_UTILITIES_H */
